You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVVideoCompositionCoreAnimationTool配合AVAssetExportSession导出时自定义属性无动画

问题原因

AVVideoCompositionCoreAnimationTool离线渲染时依赖Core Animation的运行时KVC机制监听属性变化触发重绘,现有代码存在3个核心问题导致自定义属性动画失效:

  1. Swift自定义属性默认没有开启动态派发,Core Animation无法监听到progress属性变化
  2. draw(in:)方法读取的是模型层的固定progress值,没有读取动画过程中实时变化的presentation层值
  3. 动画的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 01:54:01