Section 15 : 3D Scroll Animation

Section 15 : 3D Scroll Animation - 3D 滚动动画(7’38")

Work with arrays and data models to create a loop of components in SwiftUI.

在 SwiftUI 中使用数组和数据模型创建系列组件。

为了实现课程卡片在滚动时的三维动画,需要知道卡片的具体位置,然后根据位置确定如何动画。

(1)使用 GeometryReader 获取滚动的位置

在 ForEach 循环中的调用的 SectionView 上使用⌘ 点击,在快捷菜单中选择 VStack。这是前面我们多次使用的方法了。然后将 VStack 改为 GeometryReader。GeometryReader 可以获取到位置值 geometry,可以看见卡片都堆叠起来了。我们需要将其展开,让每张卡片都有自己的一个框架。所以给 GeometryReader 加上 frame 修饰,卡片都分开了。

ForEach(sectionData) { item in              // 遍历数组
	GeometryReader { geometry in            // 获取卡片的位置
		SectionView(section: item)          // 子视图
	}
    .frame(width: 275, height: 275)          // 让卡片分开
}

(2)使用 GeometryReader 获取到的值为 SectionView 添加 3D 动画修饰。

GeometryReader 可以获得每个框架的位置值,包括宽度、高度、各个顶点的位置等等。现在为 SectionView 组件添加 3D 动画修饰 rotation3DEffect,并且设定参数。

 .rotation3DEffect(
     Angle(degrees: Double(geometry.frame(in: .global).minX - 30) / -20), 
     axis: (x: 0, y: 10, z: 0)
 )

第一个参数是通过 geometry 的值计算的旋转角度,大家可以自己试着改变值来测试,比如 Angle(degress: 90)。这里使用了 geometry 的 frame 的值中的 minX 。minX、minY、maxX、maxY 都是 CGRect 的属性,表示左、上、右、下四条边的位置。这说明,如果是垂直方向的滚动动画,那就不能选择 minX,而是应该选择 minY。CGRect 还有很多属性,当然也包括我们最熟悉的 width 和 height,都可以通过文档查到。这里看一下各个函数的返回值类型。

geometry → GeometryProxy

frame -> CGRect

minX -> CGFloat

可以看出最终到 minX 执行后的返回值类型是 CGFloat,再经过 Double 强转后成为 Double 类型以满足 degrees 参数的需要。minX 就是卡片起始距离屏幕左侧的值,我们在padding中设置的 30,所以要减去 30 来保证起始动画的角度为 0。而除以 -20 则是为了让旋转的变化幅度减少,其中负数是为了让起始位置更符合视觉效果习惯。

第二个参数 axis 是对三个轴的规定,具体数值大小的含义我也还没有完全明白。只是知道 0 值为禁用。因为我们的卡片旋转的方向是绕着 y 轴(屏幕的纵向),所以只给 y 轴设定了参数。

(3)调整堆栈的间距

现在看起来卡片在滚动时三维动画效果还是不错的,但是卡片相互距离有些远。修改 HStack 的 spacing 来调整卡片间的距离。

本节小结

本节代码请参见 GitHub码云

  • GeometryReader 可以获取到位置,通过 .frame 方法获得类型为 CGRect 的值。
  • CGRect 包括很多属性:minX,minY,maxX,maxY,width,height……都是 CGFloat 类型的值
  • 水平滚动初始位置要使用 minX,禁用 x 和 z 轴;垂直滚动初始位置要选择 minY,禁用 y 和 z 轴。
  • 起始位置记得要减去 padding 等修饰设置的量,保证默认值是从 0 开始
  • 角度设的越大,旋转的越“疯狂”,可以用除以某个常数让动画“温和”一些。
  • 再次用到了强转

接下来

模态显示

发布了51 篇原创文章 · 获赞 15 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/hh680821/article/details/105086207