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

CALayer遮罩动画完成后未消失问题求助

解决遮罩动画结束后恢复原状的问题

嘿,我来帮你搞定这个问题~你遇到的情况其实是Core Animation的一个常见特性导致的:CAKeyframeAnimation默认只是临时修改图层的视觉表现,动画结束后会自动还原到图层的原始属性值,所以你的遮罩会变回初始的120x100大小,而不是保持放大后的状态。

解决方案:让动画结束后保持最终状态

你需要做两个关键设置,同时手动更新图层的实际属性,确保视觉和数据一致:

  • 给动画添加fillMode = .forwards和removedOnCompletion = false,让动画结束后停留在最后一帧
  • 手动更新mask的bounds属性,同步到动画的最终值(因为动画只修改「呈现层」,不会改「模型层」的属性)

修改后的代码

把你原来的动画代码替换成下面这段:

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
    let keyFrameAnimation = CAKeyframeAnimation(keyPath: "bounds")
    keyFrameAnimation.duration = 1
    keyFrameAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)]
    
    let initialBounds = NSValue(cgRect: self.mask!.bounds)
    let secondBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 110, height: 90))
    let finalBounds = NSValue(cgRect: CGRect(x: 0, y: 0, width: 6000, height: 5000))
    
    keyFrameAnimation.values = [initialBounds, secondBounds, finalBounds]
    keyFrameAnimation.keyTimes = [0, 0.3, 1]
    
    // 关键设置:动画结束后保持最后一帧状态
    keyFrameAnimation.fillMode = .forwards
    keyFrameAnimation.removedOnCompletion = false
    
    self.mask!.add(keyFrameAnimation, forKey: "bounds")
    
    // 同步更新mask的实际bounds,避免后续操作导致状态回退
    self.mask?.bounds = finalBounds.cgRectValue
}

原理说明

  • fillMode = .forwards:告诉动画在结束后保持最后一帧的视觉效果
  • removedOnCompletion = false:防止动画完成后被系统自动移除,这样fillMode的设置才能生效
  • 手动更新bounds:Core Animation的动画是作用在「呈现层」(layer.presentation())上的,不会修改「模型层」(layer本身)的属性。如果只靠fillMode,后续如果对图层有其他操作,可能会触发重绘,导致状态回退到原始值,所以手动同步模型层的属性是更稳妥的做法。

内容的提问来源于stack exchange,提问作者Steve Left

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:06:14