如何消除我的 CABasicAnimation 中的 "jump"?
How do eliminate the "jump" in my CABasicAnimation?
使用此代码:
func rotateTheView(_ aView: UIView, inClockwiseDirection isClockwise: Bool) {
let multiplier = (isClockwise ? 1 : -1)
let key = (isClockwise ? "Spin" : "Rotate")
var rotation: CABasicAnimation?
rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation!.fromValue = Int(0)
let multiplicand = multiplier * 2
rotation!.toValue = Int(Double(multiplicand) * .pi)
rotation!.duration = 30 // Speed
rotation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
rotation!.repeatCount = HUGE //HUGE_VALF Repeat forever.
aView.layer.add(rotation!, forKey: key)
}
我得到了我想要的动画。 (一个轮子旋转,或者一个细胞在相反的方向上旋转得足够快以始终保持正确的正面朝上)。
但是,当 30 秒(持续时间)结束时,会出现闪烁,因为视图会跳回动画之前的样子。
我知道它应该以这种方式工作。
如何将旋转应用于 "before" 图像,以便在持续时间到期时我看不到任何单元格跳跃?
增加动画的持续时间会减慢轮子的旋转速度,因此这不是一个合适的解决方案。
如果 #22521690 适用,我不明白如何 - 我没有明确的 CATransaction。
在将动画应用到图层后的下一行,将要设置动画的 属性 设置为其结束值。
因为一个动画是"in-flight",正常显示的层是覆盖了presentation layer,一个特殊的动画层。
动画完成后,表示层为hidden/removed,实际层暴露。如果它和动画结束时的表现层是相同的状态那么就没有跳转。
该代码可能如下所示:
func rotateTheView(_ aView: UIView, inClockwiseDirection isClockwise: Bool) {
let multiplier = (isClockwise ? 1 : -1)
let key = (isClockwise ? "Spin" : "Rotate")
var rotation: CABasicAnimation?
rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation!.fromValue = 0.0
let multiplicand = multiplier * 2
let finalAngle = Double(multiplicand) * .pi
rotation!.toValue = finalAngle
rotation!.duration = 30 // Speed
rotation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
rotation!.repeatCount = HUGE //HUGE_VALF Repeat forever.
aView.layer.add(rotation!, forKey: key)
//-------------------
//Set the final transform on the layer to the final rotation,
//but without animation
CATransaction.begin()
CATransaction.setDisableActions(true)
let finalTransform = CATransform3DMakeRotation(CGFloat(finalAngle), 0.0, 0.0, 1.0)
aView.layer.transform = finalTransform
CATransaction.commit()
//-------------------
}
尝试
rotation!.toValue = Double(multiplicand) * .pi
而不是
rotation!.toValue = Int(Double(multiplicand) * .pi)
问题在于因 Int 转换而丢失的弧度精度。
使用此代码:
func rotateTheView(_ aView: UIView, inClockwiseDirection isClockwise: Bool) {
let multiplier = (isClockwise ? 1 : -1)
let key = (isClockwise ? "Spin" : "Rotate")
var rotation: CABasicAnimation?
rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation!.fromValue = Int(0)
let multiplicand = multiplier * 2
rotation!.toValue = Int(Double(multiplicand) * .pi)
rotation!.duration = 30 // Speed
rotation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
rotation!.repeatCount = HUGE //HUGE_VALF Repeat forever.
aView.layer.add(rotation!, forKey: key)
}
我得到了我想要的动画。 (一个轮子旋转,或者一个细胞在相反的方向上旋转得足够快以始终保持正确的正面朝上)。
但是,当 30 秒(持续时间)结束时,会出现闪烁,因为视图会跳回动画之前的样子。
我知道它应该以这种方式工作。
如何将旋转应用于 "before" 图像,以便在持续时间到期时我看不到任何单元格跳跃?
增加动画的持续时间会减慢轮子的旋转速度,因此这不是一个合适的解决方案。
如果 #22521690 适用,我不明白如何 - 我没有明确的 CATransaction。
在将动画应用到图层后的下一行,将要设置动画的 属性 设置为其结束值。
因为一个动画是"in-flight",正常显示的层是覆盖了presentation layer,一个特殊的动画层。
动画完成后,表示层为hidden/removed,实际层暴露。如果它和动画结束时的表现层是相同的状态那么就没有跳转。
该代码可能如下所示:
func rotateTheView(_ aView: UIView, inClockwiseDirection isClockwise: Bool) {
let multiplier = (isClockwise ? 1 : -1)
let key = (isClockwise ? "Spin" : "Rotate")
var rotation: CABasicAnimation?
rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation!.fromValue = 0.0
let multiplicand = multiplier * 2
let finalAngle = Double(multiplicand) * .pi
rotation!.toValue = finalAngle
rotation!.duration = 30 // Speed
rotation!.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
rotation!.repeatCount = HUGE //HUGE_VALF Repeat forever.
aView.layer.add(rotation!, forKey: key)
//-------------------
//Set the final transform on the layer to the final rotation,
//but without animation
CATransaction.begin()
CATransaction.setDisableActions(true)
let finalTransform = CATransform3DMakeRotation(CGFloat(finalAngle), 0.0, 0.0, 1.0)
aView.layer.transform = finalTransform
CATransaction.commit()
//-------------------
}
尝试
rotation!.toValue = Double(multiplicand) * .pi
而不是
rotation!.toValue = Int(Double(multiplicand) * .pi)
问题在于因 Int 转换而丢失的弧度精度。