如何在路径末尾以负时间偏移量停止CAKeyframeAnimation

kel*_*lin 5 animation objective-c ios

我的应用中有一个屏幕,用户可以看到沿着弧线飞行的云.此举在CAKeyframeAnimation的帮助下实现并正常工作.但我想改进动画,以便当用户打开屏幕时,云必须看起来已经是动画.这意味着云应该在弧的中间某处.我正在实现它:

theKeyframeAnimation.timeOffset = randomTimeOffset;
Run Code Online (Sandbox Code Playgroud)

动画从给定时间开始(偏移为负).但!当云到达路径的末尾时,动画不会停止.云继续从路径的开始移动!似乎动画持续时间不会改变.

我试图通过在特定时间后删除动画来解决这个问题:

NSTimeInterval removingDelay = theKeyframeAnimation.duration + theKeyframeAnimation.offset;
dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW,
                                             (int64_t)(removingDelay * NSEC_PER_SEC));
dispatch_after(dispatchTime, dispatch_get_main_queue(), ^
               {
                   [cloud.layer removeAnimationForKey:@"animation_along_arc"];
               });
Run Code Online (Sandbox Code Playgroud)

但这种解决方案效果不佳.动画时间和发送时间不同步.实际上动画在比所需时间晚约0.5秒被移除.


更新: 现在我看到了可能的解决方案.我可以使用CAAnimationGroup包装每个动画.然后设置动画组的持续时间:

animationGroup.animations = @[theKeyframeAnima];
animationGroup.duration = theKeyframeAnima.duration + theKeyframeAnima.timeOffset;
Run Code Online (Sandbox Code Playgroud)

这是我发现的最优雅的解决方案.欢迎任何建议.

更新2:最后一个解决方案也不起作用.可能我应该剪切传球而不是改变时间偏移......

kel*_*lin 4

我找到了解决方案!问题不在于 CAKeyframeAnimation,而在于 CAMediaTiming。在这篇博客中解释了timeOffset实际上改变了动画周期,而不是时间。

为了实现我的目的,我应该使用beginTime属性:

 NSTimeInterval currentTime = [targetLayer convertTime:CACurrentMediaTime()
                                             fromLayer:nil];
 anim.beginTime = currentTime + timeOffset;
 anim.duration = duration + timeOffset;
Run Code Online (Sandbox Code Playgroud)