我试图导出一个视频文件与CALayer
叠加和多个附加CAAnimation
链接随着时间的推移。为此,我使用AVVideoCompositionCoreAnimationTool
。
我的CABasicAnimation
被抵消他们的beginTime
链接。在animationDidStop(_:finished:)
里面我更新了相应的CALayer
的动画属性。
我从下面的代码示例中删除了大部分样板文件......
/* AnimationChainer is A simple class whose instance will
* update a CALayer's model to reflect the final state of
* the animation. a translation on the y-axis in this case. */
class AnimationChainer: NSObject, CAAnimationDelegate {
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
let val = anim.value(forKey: "yTranslation") as! CGFloat
let layer = anim.value(forKey: "layer") as! CALayer
CATransaction.begin()
CATransaction.setDisableActions(true)
layer.transform = CATransform3DMakeTranslation(0.0, val, 0.0)
CATransaction.commit()
}
}
/* animation setup - a layer going up by 200pt then back to original pos. */
let chainer: AnimationChainer!
let interval = 2
let movingLayer = CALayer()
let translateOnceAnimation = CABasicAnimation(keyPath: "transform.translation.y")
translateOnceAnimation.duration = 0.4
translateOnceAnimation.fromValue = 0
translateOnceAnimation.byValue = -200
translateOnceAnimation.isRemovedOnCompletion = false
translateOnceAnimation.fillMode = .forwards
translateOnceAnimation.setValue(-200, forKey: "yTranslation")
translateOnceAnimation.setValue(movingLayer, forKey: "layer")
translateOnceAnimation.delegate = chainer
translateOnceAnimation.beginTime = AVCoreAnimationBeginTimeAtZero
let translateTwiceAnimation = CABasicAnimation(keyPath: "transform.translation.y")
translateTwiceAnimation.duration = 0.4
translateTwiceAnimation.fromValue = -200
translateTwiceAnimation.byValue = 200
translateTwiceAnimation.isRemovedOnCompletion = false
translateTwiceAnimation.fillMode = .forwards
translateTwiceAnimation.setValue(0.0, forKey: "yTranslation")
translateTwiceAnimation.setValue(movingLayer, forKey: "layer")
translateTwiceAnimation.delegate = chainer
translateTwiceAnimation.beginTime = AVCoreAnimationBeginTimeAtZero + interval
movingLayer.add(translateOnceAnimation, forKey: nil)
movingLayer.add(translateTwiceAnimation, forKey: nil)
let parentLayer = CALayer()
parentLayer.addSublayer(movingLayer)
/* end of animation setup */
let compo: AVMutableComposition!
let videoCompo: AVMutableVideoComposition!
let videoLayer: CALayer!
videoCompo.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
let exporter = AVAssetExportSession(asset: compo, presetName: AVAssetExportPresetHighestQuality)
exporter?.videoComposition = videoCompo
exporter?.exportAsynchronously {
self.exportDidFinish(exporter!)
}
当我在视图控制器的根视图上绑定动画层时,它很有效。但每当我使用它与AVVideoCompositionCoreAnimationTool
时,animationDidStop(_:finished:)
被调用,但是以随机顺序。导致动画属性的最终状态错误。
最奇怪的是,如果我在animationDidStop(_:finished:)
中放置一个断点,它就可以了!
另一个令人不安的结果是:如果我删除委托它仍然有效...可能是由于fillMode。但我无法完全解释。
在现实生活中,动画在CATransaction中运行,与壁钟相对应。它们有一个开头,一个中间和一个结尾。动画服务器在runloop的每个转弯处实时检查情况,并根据需要推进帧。
但是使用AVSynchronizedLayer或AVVideoCompositionCoreAnimationTool时,不涉及挂钟;没有动画服务器。动画被冻结,其帧通过计算映射到视频的时间码。因此,基于交易的技术不起作用;你所拥有的就是各个框架。
正如您所说,填充模式在这种情况下是一个很大的帮助。