动画CALayer的安全方法
Posted
技术标签:
【中文标题】动画CALayer的安全方法【英文标题】:safe way to animate CALayer 【发布时间】:2020-09-21 05:36:51 【问题描述】:当我在寻找 CALayer 动画时,我找到了这样的解决方案:
let basicAnimation = CABasicAnimation(keyPath: "opacity")
basicAnimation.fromValue = 0
basicAnimation.toValue = 1
basicAnimation.duration = 0.3
add(basicAnimation, forKey: "opacity")
但是fromValue和toValue都是Any类型,作为key我们可以使用任意字符串,这是不安全的。有没有更好的方法来使用最新的 Swift 功能?
【问题讨论】:
【参考方案1】:我想出了使用非常简单的解决方案:
layer.animate(.init(
keyPath: \.opacity,
value: "1", // this will produce an error
duration: 0.3)
)
layer.animate(.init(
keyPath: \.opacity,
value: 1, // correct
duration: 0.3)
)
layer.animate(.init(
keyPath: \.backgroundColor,
value: UIColor.red, // this will produce an error
duration: 0.3,
timingFunction: .init(name: .easeOut),
beginFromCurrentState: true)
)
layer.animate(.init(
keyPath: \.backgroundColor,
value: UIColor.red.cgColor, // correct
duration: 0.3,
timingFunction: .init(name: .easeOut),
beginFromCurrentState: true)
)
而解决方案代码是:
import QuartzCore
extension CALayer
struct Animation<Value>
let keyPath: ReferenceWritableKeyPath<CALayer, Value>
let value: Value
let duration: TimeInterval
let timingFunction: CAMediaTimingFunction? = nil
let beginFromCurrentState = false
@discardableResult func animate<Value>(
_ animation: Animation<Value>,
completionHandler: (() -> Void)? = nil)
-> CABasicAnimation?
CATransaction.begin()
CATransaction.setCompletionBlock(completionHandler)
defer
// update actual value with the final one
self[keyPath: animation.keyPath] = animation.value
CATransaction.commit()
guard animation.duration > 0 else return nil
let fromValueLayer: CALayer
if animation.beginFromCurrentState, let presentation = presentation()
fromValueLayer = presentation
else
fromValueLayer = self
let basicAnimation = CABasicAnimation(
keyPath: NSExpression(forKeyPath: animation.keyPath).keyPath
)
basicAnimation.timingFunction = animation.timingFunction
basicAnimation.fromValue = fromValueLayer[keyPath: animation.keyPath]
basicAnimation.toValue = animation.value
basicAnimation.duration = animation.duration
add(basicAnimation, forKey: basicAnimation.keyPath)
return basicAnimation
优点:
在 CALayer 上提供 keyPath 的自动补全功能 值类型取决于 keyPath,因此您将无法设置错误的值 清除代码缺点:
我们仍然可以选择不可动画的 keyPath【讨论】:
以上是关于动画CALayer的安全方法的主要内容,如果未能解决你的问题,请参考以下文章