2025.01.15 工作变动原因,故将一些工作期间Tapd内部写的Wiki文档转移到个人博客。
开发中,对视图(证书)做一个伪3D旋转动画,在此记录一下开发遇到的问题和解决思路。
一、iOS核心动画 —— 变换
在iOS中,利用 CATransform3D 利用可以将扁平物体转换成三维空间对象。
实际上 UIView 的 transform 属性是一个 CGAffineTransform 类型,用于在二维空间做旋转,缩放和平移。
而在iOS开发中, Core Animation 提供了一系列函数,对完全没有数学基础的开发者也能够简单地做一些变换,例如以下三个用来创建和组合 CATransform3D 类型的矩阵。
CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)
CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz)
CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)
这里开发要达到的效果是 证书180度旋转的动画,以下是实际运行代码:
这里使用了 CATransform3DMakeRotation 对视图进行3D旋转,先是沿着Y轴旋转180度,然后再一秒内旋转回原位置,代码底层实现的详细就不在这里解释了,具体效果如下:
在开发中,发现动画过程里的视图明显 位置和层级发生了变化,考虑到这个情况,认为可能是渲染中,视图的层级(优先级)发生了变化,导致了既展示不全、又会盖到别的视图上面的问题。
二、UIView层级保持在上方
鉴于开发中遇到的问题后,查阅很多资料后发现了三种办法:
第一种:
/* The Z component of the layer's position in its superlayer. Defaults to zero. Animatable. */
// 此方法改变层级结构只会改变视图渲染的位置,事件响应链并不会改变。
UIView().layer.zPosition = 1000
第二种:
// 常用,把view挪到最上层
UIView().bringSubviewToFront(UIView())
第三种:
// 常用于弹窗,把view加在window上
let keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow }
keyWindow?.addSubview(UIView())
这里使用了zPosition来解决 动画渲染中的层级问题,顺便也解决了 CATransform3DMakeRotation 动画旋转消失的问题(猜测是渲染时透视点纵深不足影响导致旋转时动画消失)。
依次设置证书的zPosition、底图的zPosition、渐变底图的zPosition后(按优先级),顺利解决了动画问题。最终效果如下: