首先普及一下iOS开发中的动画矩阵变换
大家知道, UIView中的transform表示的是2D的矩阵,而CALayer中却是3D矩阵,它包含了3D变换。
在UIView里面的transform已经在Apple官方SDK文档里面有详细的介绍,而且框架也提供了详细的变换方法。在3D的方式下大部分情况与2D相同,主要是旋转变换, 需要较强的空间思维能力。变换方法原型: CATransform3D, 其中进行三维翻转的函数:CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z); 第一个参数是旋转角度,后面三个参数形成一个围绕其旋转的向量,起点位置由UIView的center属性标识。
在这里需要说明的是在3D变换的时候,如果是变换的向量和屏幕垂直(z轴),那么就会相当于2D的旋转变化。如果不是垂直的,系统会现将整个画面调整到与这个向量垂直(没有动画),再进行旋转。所以会形成一个跳跃,破坏动画的连贯。
所以如果有这类变换的情况建议考虑动画的连贯性(体验!),先将view动画变换到和向量垂直,然后进行旋转,最后再恢复和屏幕平行。
使用CATransform3DMakeRotation实现小米运动首页效果
Swift极大提高了效率, 这个小Demo代码不超过200行, 感兴趣的小伙伴可移步MIDemo
- 效果可参考如下:
主要使用CATransform3DMakeRotation函数进行3D矩阵变换, 实质上将一张平面图通过绕其X轴进行角度偏转, 偏转的角度由上拉的距离经定值特殊计算而来
let offsetH : CGFloat = 406.0; // 头部高度
if ((offsetH - slideH)/210) > 0 { // 判断是否上推, slideH是滑动距离
dataImageView.layer.transform = CATransform3DMakeRotation(((offsetH - slideH) / 210) * CGFloat(M_PI_2), 0.3, 0, 0)
}
以下是小三角往复旋转的实现, 同样使用UIView的CGAffineTransform函数进行三维矩阵变换
if isSlideMax { // 如果向下滑动距离到临界值
tipsLabel.text = "松手开始同步"
UIView.animate(withDuration: 0.3, animations: {
self.tipsImageView.transform = CGAffineTransform.init(rotationAngle:CGFloat(NSNumber(value: M_PI)))
})
} else {
tipsLabel.text = "下拉同步数据"
UIView.animate(withDuration: 0.3, animations: {
self.tipsImageView.transform = CGAffineTransform.init(rotationAngle: CGFloat(NSNumber(value: M_PI * 2)))
})
}