CATransaction如何取消?CALayer事务暂停与取消可行性咨询
当然可行!针对你用CATransaction启动的这个opacity过渡动画,不管是中途取消还是暂停/恢复,都有成熟的实现方案,我给你详细拆解:
一、取消动画的两种常用方式
CATransaction创建的隐式动画本质上是给CALayer自动添加了一个CABasicAnimation,所以我们可以通过操作这个动画或者直接修改layer属性来终止它:
方式1:直接移除对应动画
隐式动画默认会以目标属性名作为动画的key(这里就是opacity),直接调用移除方法就能立刻终止动画,layer会停在当前动画执行到的进度状态:
// Swift self.myLayer.removeAnimation(forKey: "opacity") // Objective-C [self.myLayer removeAnimationForKey:@"opacity"];
方式2:立即跳转到动画目标状态
如果希望取消动画的同时,让layer立刻变成最终的opacity = 1状态,可以开启一个禁用动画的新事务,直接设置属性值:
// Swift CATransaction.begin() CATransaction.setDisableActions(true) // 关闭隐式动画 self.myLayer.opacity = 1 CATransaction.commit() // Objective-C [CATransaction begin]; [CATransaction setDisableActions:YES]; self.myLayer.opacity = 1; [CATransaction commit];
二、暂停/恢复动画的实现
如果想让动画暂时停在当前帧,之后还能继续播放,可以通过调整CALayer的时间系统来实现——核心是修改speed和timeOffset属性:
暂停动画的代码
// Swift func pauseLayer(_ layer: CALayer) { // 获取当前媒体时间转换为layer本地时间 let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil) // 将layer的时间速度设为0,暂停时间推进 layer.speed = 0.0 // 记录当前暂停的时间点 layer.timeOffset = pausedTime } // 调用 pauseLayer(self.myLayer) // Objective-C - (void)pauseLayer:(CALayer *)layer { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; layer.speed = 0.0; layer.timeOffset = pausedTime; } // 调用 [self pauseLayer:self.myLayer];
恢复动画的代码
// Swift func resumeLayer(_ layer: CALayer) { let pausedTime = layer.timeOffset // 重置时间速度为正常 layer.speed = 1.0 // 清空之前的时间偏移 layer.timeOffset = 0.0 layer.beginTime = 0.0 // 计算从暂停到现在的时间差,调整beginTime让动画从暂停点继续 let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime layer.beginTime = timeSincePause } // 调用 resumeLayer(self.myLayer) // Objective-C - (void)resumeLayer:(CALayer *)layer { CFTimeInterval pausedTime = layer.timeOffset; layer.speed = 1.0; layer.timeOffset = 0.0; layer.beginTime = 0.0; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; layer.beginTime = timeSincePause; } // 调用 [self resumeLayer:self.myLayer];
原理说明:CALayer的动画进度由自身的时间轴驱动,当speed设为0时,时间轴停止推进,动画就会停在当前帧;恢复时通过调整beginTime,让动画从暂停的时间点继续执行,保证进度不会丢失。
内容的提问来源于stack exchange,提问作者Gizmodo
相关产品推荐
相关产品推荐

