You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:02:05