CAAnimation使用timeOffset续播时多余前2秒的解决方法咨询
解决CAAnimation续播时重复前序内容的问题
这个问题我之前调试动画的时候也踩过坑,核心是没搞明白CAAnimation基于CALayer时间系统的运行逻辑——你直接设置timeOffset=2.0恢复播放时,没有对齐当前的媒体时间,导致动画的时间轴出现了重叠,才会重复前2秒的内容。
问题根源
当你暂停动画时,只是把layer.speed设为0并记录了timeOffset=2.0,但页面跳转过程中,系统的媒体时间(CACurrentMediaTime())一直在流逝。当你返回页面恢复动画时,如果只重置speed=1并保留原来的timeOffset,CALayer会基于初始的beginTime(默认是0)来计算动画进度,相当于让动画从“当前媒体时间 - 初始beginTime”的位置,再加上timeOffset的偏移,这就会导致前2秒的内容被重复播放。
正确的暂停&续播方案
我们需要准确记录暂停时的动画时间点,恢复时通过调整layer.beginTime来对齐当前媒体时间,让动画从暂停位置无缝续播:
1. 暂停动画时记录准确时间
在需要暂停的时机(比如页面即将跳转的viewWillDisappear),用convertTime:fromLayer:获取动画的真实播放时间并保存:
// 假设动画所在的layer是self.animationLayer @property (nonatomic, assign) CFTimeInterval recordedPauseTime; - (void)pauseAnimation { // 获取当前动画的已播放时间 CFTimeInterval pausedTime = [self.animationLayer convertTime:CACurrentMediaTime() fromLayer:nil]; // 冻结layer时间 self.animationLayer.speed = 0.0; // 记录当前时间偏移 self.animationLayer.timeOffset = pausedTime; // 保存这个时间,用于后续恢复 self.recordedPauseTime = pausedTime; }
2. 页面返回后恢复动画
在viewWillAppear中,通过调整beginTime让动画时间轴对齐当前媒体时间:
- (void)resumeAnimation { // 获取当前系统媒体时间 CFTimeInterval currentTime = [self.animationLayer convertTime:CACurrentMediaTime() fromLayer:nil]; // 计算需要偏移的beginTime,让动画从暂停点继续 self.animationLayer.beginTime = currentTime - self.recordedPauseTime; // 恢复layer的播放速度 self.animationLayer.speed = 1.0; // 重置timeOffset和beginTime的临时偏移,避免后续干扰 self.animationLayer.timeOffset = 0.0; self.animationLayer.beginTime = 0.0; }
另一种备选方案:重新创建动画并设置起始时间
如果觉得调整layer属性太绕,也可以直接重新创建动画,通过设置beginTime让它从指定进度开始播放:
// 假设原动画是self.originalAnimation CAAnimation *resumedAnimation = [self.originalAnimation copy]; // 设置动画的起始时间:当前媒体时间减去已经播放的2秒 resumedAnimation.beginTime = CACurrentMediaTime() - 2.0; // 移除旧动画,添加新动画 [self.animationLayer removeAnimationForKey:@"yourAnimationKey"]; [self.animationLayer addAnimation:resumedAnimation forKey:@"yourAnimationKey"];
这种方法更直观,但需要保留原动画的副本,适合简单场景。
关键注意点
- 一定要在页面消失前(比如
viewWillDisappear)暂停动画并记录时间,避免页面跳转时动画在后台继续运行(虽然speed=0会冻结,但系统时间还是会走)。 - 恢复时不要直接修改
timeOffset,而是通过beginTime对齐当前时间,这是避免重复播放的核心。
内容的提问来源于stack exchange,提问作者Lowji
相关产品推荐
相关产品推荐

