动画CALayer的蒙版大小更改

Ale*_*pty 28 iphone core-animation mask objective-c calayer

我有一个UIView子类,它使用一个CAShapeLayer掩码CALayer.面具使用不同的形状,在剩下的角落有三个圆角和一个切出的矩形.

当我UIView使用标准动画块调整大小时,UIView自身和它的CALayer大小调整就好了.然而,面具立即应用,这导致一些绘图问题.

我已经尝试使用a动画屏幕的大小调整,CABasicAnimation但没有任何运气调整大小动画.

我可以以某种方式在面具上实现动画调整大小效果吗?我是否需要摆脱面具,或者我必须改变一下我当前绘制面具的方式(使用- (void)drawInContext:(CGContextRef)ctx).

干杯,亚历克斯

Kek*_*koa 44

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

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

  • mask属性本身不可动画.
  • 由于蒙版是CALayer,因此可以自行设置动画.
  • 帧不可动画,使用边界和位置.这可能不适用于您(如果您没有尝试为框架设置动画),但这对我来说是一个问题.(参见Apple QA 1620)
  • 视图图层的蒙版未绑定到UIView,因此它不会接收应用于视图图层的核心动画事务.
  • 我们正在直接修改CALayer,因此我们不能指望UIView会知道我们要做什么,因此UIView动画不会创建核心动画事务以包含对属性的更改.

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

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

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];
Run Code Online (Sandbox Code Playgroud)


sti*_*igi 10

我使用a 通过设置到该形状图层CAShapeLayer来屏蔽a .UIViewself.layer.mask

要在视图大小发生变化时-setBounds:为蒙版设置动画,如果在动画过程中更改了边界,我会覆盖蒙版图层路径的动画.

这是我实现它的方式:

- (void)setBounds:(CGRect)bounds
{
    [super setBounds:bounds];
    CAPropertyAnimation *boundsAnimation = (CABasicAnimation *)[self.layer animationForKey:@"bounds"];

    // update the mask
    self.maskLayer.frame = self.layer.bounds;

    // if the bounds change happens within an animation, also animate the mask path
    if (!boundsAnimation) {
        self.maskLayer.path = [self createMaskPath];
    } else {
        // copying the original animation allows us to keep all animation settings
        CABasicAnimation *animation = [boundsAnimation copy];
        animation.keyPath = @"path";

        CGPathRef newPath = [self createMaskPath];
        animation.fromValue = (id)self.maskLayer.path;
        animation.toValue = (__bridge id)newPath;

        self.maskLayer.path = newPath;

        [self.maskLayer addAnimation:animation forKey:@"path"];
    }
}
Run Code Online (Sandbox Code Playgroud)

(例如self.maskLayer,设置为`self.layer.mask)

-createMaskPath计算用于掩盖视图的CGPathRef.我还更新了掩码路径-layoutSubviews.


Cor*_*rin 5

CALayer的mask属性不具有动画效果,这解释了你在这方面缺乏运气.

面具的绘制是否取决于面具的边框/边界?(你能提供一些代码吗?)掩码是否设置了needsDisplayOnBoundsChange属性?

干杯,科林


Nic*_*247 5

要为UIView:子类UIView的遮罩层的边界变化设置动画,并使用CATransaction为蒙版设置动画 - 类似于Kekodas答案,但更通用:

@implementation UIMaskView

- (void) layoutSubviews {
    [super layoutSubviews];

    CAAnimation* animation = [self.layer animationForKey:@"bounds"];
    if (animation) {
        [CATransaction begin];
        [CATransaction setAnimationDuration:animation.duration];
    }

    self.layer.mask.bounds = self.layer.bounds;
    if (animation) {
        [CATransaction commit];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)