且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

动画CALayer的蒙版大小更改

更新时间:2022-12-30 10:19:16

我找到了解决这个问题的方法。其他答案部分正确并且有用。

I found the solution to this problem. Other answers are partially correct and are helpful.

以下几点对于理解解决方案非常重要:

The following points are important to understanding the solution:


  • 掩码属性

  • 由于蒙版是CALayer,因此可以自行设置动画。

  • 帧不可动画,使用边界和位置。这可能不适用于您(如果您没有尝试为框架设置动画),但这对我来说是一个问题。 (参见 Apple QA 1620

  • 视图层的掩码与UIView无关,因此它不会接收应用于视图层的核心动画事务。

  • 我们正在直接修改CALayer,所以我们不能指望UIView会知道我们要做什么,所以UIView动画不会创建核心动画事务来包含对我们属性的更改。

  • The mask property is not animatable itself.
  • Since the mask is a CALayer it can be animated on its own.
  • Frame is not animatable, use bounds and position. This may not apply to you(if you weren't trying to animate the frame), but was an issue for me. (See Apple QA 1620)
  • A view layer's mask is not tied to UIView so it will not receive the core animation transaction that is applied to the view's layer.
  • We are modifying the CALayer directly, so we can't expect that UIView will have any idea of what we are trying to do, so the UIView animation won't create the core animation transaction to include changes to our properties.

为了解决这个问题,我们将不得不自己使用Core Animation,并且不能依赖UIView动画块来为我们工作。

In order to solve, we are going to have to tap into Core Animation ourselves, and can't rely on the UIView animation block to do the work for us.

只需创建一个 CATransaction ,其持续时间与 [UIView animateWithDuration]相同:...] 。这将创建一个单独的动画,但如果您的持续时间和缓动功能相同,它应该与动画块中的其他动画完全一致。

Simply create a CATransaction with the same duration that you are using with [UIView animateWithDuration:...]. This will create a separate animation, but if your durations and easing function is the same, it should animate exactly with the other animations in your animation block.

NSTimeInterval duration = 0.5;// match this to the value of the UIView animateWithDuration: call

[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:duration] forKey:kCATransactionAnimationDuration];

self.myView.layer.mask.position = CGPointMake(newX, 0);
self.myView.layer.mask.bounds = CGRectMake(0, 0, newWidth, newHeight);

[CATransaction commit];