使用 UIViewPropertyAnimator 同步动画 CALayer 属性 和 UIView
Synchronously animate CALayer property and UIView with UIViewPropertyAnimator
我正在使用 UIViewPropertyAnimator
为视图的位置设置动画。但是,我也想为 CALayer 属性设置动画,例如 borderColor
。目前,它没有动画并在开始时立即发生变化,如下所示:
这是我的代码:
class ViewController: UIViewController {
var animator: UIViewPropertyAnimator?
let squareView = UIView(frame: CGRect(x: 0, y: 40, width: 80, height: 80))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(squareView)
squareView.backgroundColor = UIColor.blue
squareView.layer.borderColor = UIColor.green.cgColor
squareView.layer.borderWidth = 6
animator = UIViewPropertyAnimator(duration: 2, curve: .easeOut, animations: {
self.squareView.frame.origin.x = 100
self.squareView.layer.borderColor = UIColor.red.cgColor
})
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.animator?.startAnimation()
}
}
}
我看了这个问题,How to synchronously animate a UIView and a CALayer,答案建议使用“显式动画,如基本动画”。它说,
If the timing function and the duration of both animations are the same then they should stay aligned.
但是,如果我使用 CABasicAnimation
,我将失去 UIViewPropertyAnimator
的所有好处,例如计时和中间停止。我还需要跟踪两者。 有什么方法可以用 UIViewPropertyAnimator
动画化 CALayer
属性吗?
CABasicAnimation 有定时和关键帧动画在中间停止。但是,要复制上面的动画:
squareView.layer.transform = CATransform3DMakeTranslation(100, 0, 0)
let fromValue = squareView.transform
let toValue = 100
let translateAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform))
translateAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
translateAnimation.fromValue = fromValue
translateAnimation.toValue = toValue
translateAnimation.valueFunction = CAValueFunction(name: .translateX)
let fromColor = squareView.layer.borderColor
let toColor = UIColor.red.cgColor
let borderColorAnimation = CABasicAnimation(keyPath: "borderColor")
borderColorAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
borderColorAnimation.fromValue = fromColor
borderColorAnimation.toValue = toColor
let groupAnimation = CAAnimationGroup()
groupAnimation.animations = [translateAnimation, borderColorAnimation]
groupAnimation.duration = 5
squareView.layer.add(groupAnimation, forKey: nil)
我正在使用 UIViewPropertyAnimator
为视图的位置设置动画。但是,我也想为 CALayer 属性设置动画,例如 borderColor
。目前,它没有动画并在开始时立即发生变化,如下所示:
这是我的代码:
class ViewController: UIViewController {
var animator: UIViewPropertyAnimator?
let squareView = UIView(frame: CGRect(x: 0, y: 40, width: 80, height: 80))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(squareView)
squareView.backgroundColor = UIColor.blue
squareView.layer.borderColor = UIColor.green.cgColor
squareView.layer.borderWidth = 6
animator = UIViewPropertyAnimator(duration: 2, curve: .easeOut, animations: {
self.squareView.frame.origin.x = 100
self.squareView.layer.borderColor = UIColor.red.cgColor
})
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.animator?.startAnimation()
}
}
}
我看了这个问题,How to synchronously animate a UIView and a CALayer,答案建议使用“显式动画,如基本动画”。它说,
If the timing function and the duration of both animations are the same then they should stay aligned.
但是,如果我使用 CABasicAnimation
,我将失去 UIViewPropertyAnimator
的所有好处,例如计时和中间停止。我还需要跟踪两者。 有什么方法可以用 UIViewPropertyAnimator
动画化 CALayer
属性吗?
CABasicAnimation 有定时和关键帧动画在中间停止。但是,要复制上面的动画:
squareView.layer.transform = CATransform3DMakeTranslation(100, 0, 0)
let fromValue = squareView.transform
let toValue = 100
let translateAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform))
translateAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
translateAnimation.fromValue = fromValue
translateAnimation.toValue = toValue
translateAnimation.valueFunction = CAValueFunction(name: .translateX)
let fromColor = squareView.layer.borderColor
let toColor = UIColor.red.cgColor
let borderColorAnimation = CABasicAnimation(keyPath: "borderColor")
borderColorAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
borderColorAnimation.fromValue = fromColor
borderColorAnimation.toValue = toColor
let groupAnimation = CAAnimationGroup()
groupAnimation.animations = [translateAnimation, borderColorAnimation]
groupAnimation.duration = 5
squareView.layer.add(groupAnimation, forKey: nil)