[英]Chaining multiple CAAnimation in a AVAssetExportSession
我正在嘗試導出帶有CALayer
覆蓋和隨時間鏈接的多個附加CAAnimation
的視頻文件。 為此,我正在使用AVVideoCompositionCoreAnimationTool
。
我的CABasicAnimation
通過偏移它們的beginTime
來鏈接。 在animationDidStop(_:finished:)
我更新了相應CALayer
animationDidStop(_:finished:)
屬性。
我從下面的代碼示例中刪除了大部分樣板...
/* 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
一起使用時, AVVideoCompositionCoreAnimationTool
animationDidStop(_:finished:)
,但順序是隨機的。 導致動畫屬性的最終狀態錯誤。
最奇怪的是,如果我在animationDidStop(_:finished:)
放置一個斷點,它將起作用!
另一個令人不安的結果是:如果我刪除委托,它仍然可以工作……可能是由於fillMode所致。 但我無法完全解釋。
在現實生活中,動畫是在CATransaction中相對於牆上時鍾運行的。 他們有一個開始,一個中間和一個結束。 動畫服務器會在運行循環的每一轉實時檢查情況,並根據需要推進幀。
但是,使用AVSynchronizedLayer或AVVideoCompositionCoreAnimationTool時,無需使用掛鍾。 沒有動畫服務器。 動畫被凍結,其幀通過計算被映射到視頻的時間碼。 因此,基於事務的技術不起作用。 您所擁有的只是各個框架。
就像您正確說的那樣,在這種情況下,填充模式很有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.