CAShapeLayer 动画无需更新路径

Posted

技术标签:

【中文标题】CAShapeLayer 动画无需更新路径【英文标题】:CAShapeLayer Animation without having to update the path 【发布时间】:2016-11-17 17:17:06 【问题描述】:

在为 CAShapeLayer 制作动画时,是否需要不断更新图层的路径,或者有没有办法单独依赖 CABasicAnimation?

在下面的示例中,我设置了四个圆形路径并绘制它们。 然后我想让它们动画消失。然而,在动画完成后,它们会弹回原来的路径。

    int radius =  halfWidth-30; //the radius is the distance out from the centre
    trackActive.path = [UIBezierPath bezierPathWithArcCenter:cicleCenter radius:radius startAngle:degreesToRadians(circleStart) endAngle:degreesToRadians(circleEnd) clockwise:true].CGPath;
    circleActive.path = [UIBezierPath bezierPathWithArcCenter:cicleCenter radius:radius startAngle:degreesToRadians(circleStart) endAngle:degreesToRadians(circleEnd) clockwise:true].CGPath;

    radius = halfWidth - 10;
    trackNew.path = [UIBezierPath bezierPathWithArcCenter:cicleCenter radius:radius startAngle:degreesToRadians(circleStart) endAngle:degreesToRadians(circleEnd) clockwise:true].CGPath;
    circleNew.path = [UIBezierPath bezierPathWithArcCenter:cicleCenter radius:radius startAngle:degreesToRadians(circleStart) endAngle:degreesToRadians(circleEnd) clockwise:true].CGPath;

    NSArray * layers = @[trackActive, circleActive, trackNew, circleNew];
    for (CAShapeLayer * layer in layers)

        [CATransaction begin];
        CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        animation.duration = 1.0f;
        animation.removedOnCompletion = false;
        animation.fromValue = @(1.0);
        animation.toValue = @(0.0);
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        [layer addAnimation:animation forKey:@"circleAnimation"];

        [CATransaction commit];
    

我知道我可以添加这个来设置新路径:

    [CATransaction setCompletionBlock:^

        //set the new path
        layer.path = [UIBezierPath bezierPathWithArcCenter:cicleCenter radius:radius startAngle:degreesToRadians(circleStart) endAngle:degreesToRadians(arcEnd) clockwise:true].CGPath;

    ];

但宁愿避免不断更新路径,而是完全依赖动画层。这可能吗?

类似:layer.path = animation.path 或 animation.updatesOriginalPath=true;可能是一厢情愿,不确定。

【问题讨论】:

您可以通过将层的strokeEnd设置为零来省略回弹效果,因为动画不会修改层的状态。 【参考方案1】:

您可以简化代码并省略弹簧效果:

[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
[CATransaction setAnimationTimingFunction: kCAMediaTimingFunctionEaseInEaseOut];
layer.strokeEnd = 0.0;
[CATransaction commit];

事务将为您创建并添加一个隐式动画对象。

【讨论】:

【参考方案2】:

您可以在动画中设置一个标志,使其保持在最后的位置并从应该开始的位置开始,如下所示:

[animation setRemovedOnCompletion:NO];
[animation setFillMode:kCAFillModeBoth];

还要检查这个答案: What exactly does removedOnCompletion = NO do?

【讨论】:

您应该避免在图层上保留动画。稍后删除或替换动画会导致意外效果。 layer.strokeEnd = 0.0addAnimation 之前的效果相同。 保留动画的另一个缺点是图层不反映它的可见状态。对于strokeEnd,它始终返回 1.0,但它显示 0.0 的值。

以上是关于CAShapeLayer 动画无需更新路径的主要内容,如果未能解决你的问题,请参考以下文章

CAShapeLayer 路径动画——缩小圆

如何为 CAShapeLayer 路径和填充颜色设置动画

CAShapeLayer 动画路径毛刺/闪烁(从椭圆到矩形并返回)

我正在为填充但未描边的 CAShapeLayer 的路径值设置动画,我想让它的动画更流畅

贝塞尔曲线与CAShapeLayer的关系以及Stroke动画

SpriteKit - 动画 SKShapeNode 形状路径