AVVideoCompositionCoreAnimationTool配合AVAssetExportSession导出时自定义属性无动画
问题原因
AVVideoCompositionCoreAnimationTool离线渲染时依赖Core Animation的运行时KVC机制监听属性变化触发重绘,现有代码存在3个核心问题导致自定义属性动画失效:
- Swift自定义属性默认没有开启动态派发,Core Animation无法监听到
progress属性变化 draw(in:)方法读取的是模型层的固定progress值,没有读取动画过程中实时变化的presentation层值- 动画的
toValue设置为50,超出了progress作为比例系数的合理取值范围,就算动画生效绘制内容也会超出画布不可见
修改方案
1. 替换CustomLayer的属性定义与逻辑
class CustomLayer: CALayer { // 用@objc dynamic开启Core Animation所需的KVO动态监听,移除不必要的@NSManaged @objc dynamic var progress: CGFloat = 0.0 override init() { super.init() // 关闭异步绘制适配离线渲染的同步环境 drawsAsynchronously = false } override init(layer: Any) { let l = layer as! CustomLayer // 先复制自定义属性再调用父类初始化,避免属性丢失 self.progress = l.progress super.init(layer: layer) } required init?(coder: NSCoder) { super.init(coder: coder) drawsAsynchronously = false } override class func needsDisplay(forKey key: String) -> Bool { if key == #keyPath(progress) { return true } return super.needsDisplay(forKey: key) } override func draw(in ctx: CGContext) { ctx.saveGState() defer { ctx.restoreGState() } // 读取presentation层的实时动画值,不要使用模型层的self.progress let currentProgress = presentation()?.progress ?? progress ctx.move(to: .zero) ctx.addLine(to: CGPoint(x: bounds.size.width * currentProgress, y: bounds.size.height * currentProgress)) ctx.setStrokeColor(UIColor.red.cgColor) ctx.setLineWidth(40) ctx.strokePath() } }
2. 修正动画参数
let anim = CABasicAnimation(keyPath: #keyPath(CustomLayer.progress)) anim.fromValue = 0.0 // 修正toValue为1.0,适配比例系数的取值范围 anim.toValue = 1.0 anim.duration = 6.0 anim.beginTime = AVCoreAnimationBeginTimeAtZero anim.isRemovedOnCompletion = false // 新增fillMode设置,保证动画结束后保持最终状态 anim.fillMode = .forwards animLayer.add(anim, forKey: nil)
修改完成后重新运行导出,即可看到红色斜线随时间从左上角向右下角延伸的动画效果。
内容的提问来源于stack exchange,提问作者msmialko
相关产品推荐
相关产品推荐

