如何阻止CATransform3DMakeScale为CALayer缩放变化添加动画?
解决捏合手势中CALayer缩放动画卡顿的问题
这个问题我太熟悉了——CALayer的属性变更默认会触发隐式动画,这就是你遇到卡顿的核心原因!每次捏合手势更新时,你设置layer.transform都会自动启动一个默认的动画,而手势的缩放值更新速度远快于动画完成速度,多个动画叠加就导致画面卡顿、跟不上手势节奏了。
最简单的解决方案:禁用本次变换的隐式动画
你只需要用CATransaction包裹住transform的设置代码,关闭当前事务的隐式动画即可:
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer { if ([gestureRecognizer state] == UIGestureRecognizerStateChanged) { pinchScale = [gestureRecognizer scale]; CALayer *layer = [self layer]; // 开启事务并禁用隐式动画 [CATransaction begin]; [CATransaction setDisableActions:YES]; // 注意:z轴缩放设为1,设为0可能导致图层显示异常 layer.transform = CATransform3DMakeScale(pinchScale, pinchScale, 1); [CATransaction commit]; } }
另一种更简洁的写法(适用于UIView子类)
如果你的代码是在UIView的子类中,也可以用UIView提供的便捷方法直接禁用动画:
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer { if ([gestureRecognizer state] == UIGestureRecognizerStateChanged) { pinchScale = [gestureRecognizer scale]; CALayer *layer = [self layer]; // UIView的方法内部会自动处理CATransaction [UIView performWithoutAnimation:^{ layer.transform = CATransform3DMakeScale(pinchScale, pinchScale, 1); }]; } }
补充说明
- 为什么原来的代码会卡顿?因为每次手势触发时,上一次的transform动画还在执行,新的动画又会被触发,Core Animation需要不断中断并重新计算动画状态,导致性能开销剧增,最终出现卡顿。
- 注意z轴缩放参数:你原来的代码里设为0,这可能导致图层被完全压缩到z轴方向,出现显示异常,建议保持为1(不缩放z轴)。
内容的提问来源于stack exchange,提问作者Shiri
相关产品推荐
相关产品推荐

