iOS 3DAnimations:旋转多个叠加视图时出现问题
iOS 3DAnimations: Issues when rotating multiple superposed views
问题
当在同一轴上同时翻转(例如 pi旋转)视图时,视图层次结构(哪个在前,哪个在后)似乎是打扰了。
详细解释
在下面的 GIF 中,带有 swift 图标的灰色视图在前面,蓝色视图在后面 .
你可以注意到,当灰度视图的第一次旋转达到pi / 2时,它的透明度似乎发生了变化。此外,当灰色完成它的第一次旋转时,它不会停留在蓝色视图后面,而是在下一次旋转期间看起来在前面。
现在重复完全相同的动画,蓝色视图现在没有应用任何颜色,但它仍在灰色视图后面的视图层次结构中,并且仍然是动画。
想要的结果
我试图实现相同的动画,将蓝色视图保持在灰色视图之上,而灰色视图没有任何明显的透明度变化。我使用 UIViewPropertyAnimator
以便稍后可以擦除动画。
代码
以下代码描述了动画所基于的简化翻转方法(作为 UIView 扩展)。
extension UIView{
func flipping(_ times: Int = 1, to direction: FoldingDirection, within duration: Double = 0.01, startAfter delay: Double = 0) {
guard times > 0 else { return }
// resets the layer anchor point depending on the current transform states of the view (calling a specific method)
self.setAnchorPoint(at: direction.anchor())
// adding perspective effect
self.layer.transform.m34 = 1 / 250
// setting rotation axis
let axis: CGPoint = {
switch direction {
case .right, .left:
return CGPoint(x: 1, y: 0)
default:
return CGPoint(x: 0, y: 1)
}
}()
let flipDuration = duration > 0 ? duration / Double(times) : 0.01
// creating animator
let animator = UIViewPropertyAnimator(duration: flipDuration, curve: .linear) {
self.layer.transform = CATransform3DRotate(self.layer.transform, .pi, axis.y, axis.x, 0)
}
animator.startAnimation(afterDelay: delay)
animator.addCompletion { (position) in
if position == .end {
self.flipping(times - 1, to: direction, within: duration * ( 1 - 1 / Double(times)), startAfter: 0)
}
}
}
}
调用动画:
greyView.flipping(3, to: .right, within: 9, startAfter: 0)
blueView.flipping(2, to: .right, within: 6, startAfter: 3)
感谢您的帮助!
编辑
经过 运行 多次测试,似乎视图层次结构在动画期间确实发生了变化:旋转似乎发生在视图平面后面。
在这种动画中,他们的Zpostion没有分配,所以你无法控制哪个更近,哪个更远。
在事件时将 zPosition 分配给层将解决您的问题。您可以比较
greyView.layer.zPosition = 20
blueView.layer.zPosition = -20
和
greyView.layer.zPosition = 200
blueView.layer.zPosition = -200
你会明白我的意思的。
问题
当在同一轴上同时翻转(例如 pi旋转)视图时,视图层次结构(哪个在前,哪个在后)似乎是打扰了。
详细解释
在下面的 GIF 中,带有 swift 图标的灰色视图在前面,蓝色视图在后面 .
你可以注意到,当灰度视图的第一次旋转达到pi / 2时,它的透明度似乎发生了变化。此外,当灰色完成它的第一次旋转时,它不会停留在蓝色视图后面,而是在下一次旋转期间看起来在前面。
现在重复完全相同的动画,蓝色视图现在没有应用任何颜色,但它仍在灰色视图后面的视图层次结构中,并且仍然是动画。
想要的结果
我试图实现相同的动画,将蓝色视图保持在灰色视图之上,而灰色视图没有任何明显的透明度变化。我使用 UIViewPropertyAnimator
以便稍后可以擦除动画。
代码
以下代码描述了动画所基于的简化翻转方法(作为 UIView 扩展)。
extension UIView{
func flipping(_ times: Int = 1, to direction: FoldingDirection, within duration: Double = 0.01, startAfter delay: Double = 0) {
guard times > 0 else { return }
// resets the layer anchor point depending on the current transform states of the view (calling a specific method)
self.setAnchorPoint(at: direction.anchor())
// adding perspective effect
self.layer.transform.m34 = 1 / 250
// setting rotation axis
let axis: CGPoint = {
switch direction {
case .right, .left:
return CGPoint(x: 1, y: 0)
default:
return CGPoint(x: 0, y: 1)
}
}()
let flipDuration = duration > 0 ? duration / Double(times) : 0.01
// creating animator
let animator = UIViewPropertyAnimator(duration: flipDuration, curve: .linear) {
self.layer.transform = CATransform3DRotate(self.layer.transform, .pi, axis.y, axis.x, 0)
}
animator.startAnimation(afterDelay: delay)
animator.addCompletion { (position) in
if position == .end {
self.flipping(times - 1, to: direction, within: duration * ( 1 - 1 / Double(times)), startAfter: 0)
}
}
}
}
调用动画:
greyView.flipping(3, to: .right, within: 9, startAfter: 0)
blueView.flipping(2, to: .right, within: 6, startAfter: 3)
感谢您的帮助!
编辑 经过 运行 多次测试,似乎视图层次结构在动画期间确实发生了变化:旋转似乎发生在视图平面后面。
在这种动画中,他们的Zpostion没有分配,所以你无法控制哪个更近,哪个更远。
在事件时将 zPosition 分配给层将解决您的问题。您可以比较
greyView.layer.zPosition = 20
blueView.layer.zPosition = -20
和
greyView.layer.zPosition = 200
blueView.layer.zPosition = -200
你会明白我的意思的。