圆弧段的笔划动画以完整笔划结束

发布于 2025-01-02 15:54:14 字数 1416 浏览 2 评论 0原文

我正在尝试为圆的一部分的外观设置动画。为了存档这个,我使用了 CABasicAnimations,它工作得很好。

动画从顶部开始,安静地移动到整个圆圈的三分之一。但是当动画结束时,圆圈立即被完全绘制出来。

我怎样才能防止这种情况发生?

这是我的自定义 UIView 的源代码:

- (void)drawRect:(CGRect)rect
{
    int radius = 100;
    int strokeWidth = 10;
    CGColorRef color = [UIColor redColor].CGColor;
    int timeInSeconds = 5;

    CGFloat startAngle = 0;
    CGFloat endAngle = 0.33;

    CAShapeLayer *circle = [CAShapeLayer layer];

    circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;

    circle.position = CGPointMake(CGRectGetMidX(self.frame)-radius, CGRectGetMidY(self.frame)-radius);

    circle.fillColor = [UIColor clearColor].CGColor;
    circle.strokeColor = color;
    circle.lineWidth = strokeWidth;

    [self.layer addSublayer:circle];

    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    drawAnimation.duration            = timeInSeconds;
    drawAnimation.repeatCount         = 1.0;
    drawAnimation.removedOnCompletion = NO;

    drawAnimation.fromValue = [NSNumber numberWithFloat:startAngle];
    drawAnimation.toValue   = [NSNumber numberWithFloat:endAngle];

    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    [circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
}

I'm trying to animate the appearance of a segment of a circle. To archive this I use a CABasicAnimations which works quiet fine.

The animation starts on top and moves quiet nicely to one third of the whole circle. But when the animation finishes, the circle is being drawn completely immediately.

How can I prevent that?

Here is the source code of my custom UIView:

- (void)drawRect:(CGRect)rect
{
    int radius = 100;
    int strokeWidth = 10;
    CGColorRef color = [UIColor redColor].CGColor;
    int timeInSeconds = 5;

    CGFloat startAngle = 0;
    CGFloat endAngle = 0.33;

    CAShapeLayer *circle = [CAShapeLayer layer];

    circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;

    circle.position = CGPointMake(CGRectGetMidX(self.frame)-radius, CGRectGetMidY(self.frame)-radius);

    circle.fillColor = [UIColor clearColor].CGColor;
    circle.strokeColor = color;
    circle.lineWidth = strokeWidth;

    [self.layer addSublayer:circle];

    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    drawAnimation.duration            = timeInSeconds;
    drawAnimation.repeatCount         = 1.0;
    drawAnimation.removedOnCompletion = NO;

    drawAnimation.fromValue = [NSNumber numberWithFloat:startAngle];
    drawAnimation.toValue   = [NSNumber numberWithFloat:endAngle];

    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    [circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

巴黎夜雨 2025-01-09 15:54:14

当您将动画应用于图层时,核心动画会创建该图层的副本并对副本的属性进行动画处理。原始层称为模型层,副本称为表示层。动画永远不会更改模型层的属性。

您尝试通过将 removedOnCompletion 设置为 NO 来修复此问题。您还必须设置动画的 fillMode 才能使其正常工作,但这并不是为属性设置动画的真正正确方法。

正确的方法是更改​​模型图层上的属性,然后应用动画。

// Change the model layer's property first.
circle.strokeEnd = endAngle;

// Then apply the animation.
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration            = timeInSeconds;
drawAnimation.fromValue = [NSNumber numberWithFloat:startAngle];
drawAnimation.toValue   = [NSNumber numberWithFloat:endAngle];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];

核心动画基础视频对此进行了解释来自WWDC 2011。我强烈推荐观看。

When you apply an animation to a layer, Core Animation creates a copy of the layer and animates the properties of the copy. The original layer is called the model layer and the copy is called the presentation layer. An animation never changes the properties of the model layer.

You tried to fix this by setting removedOnCompletion to NO. You would also have to set the fillMode of the animation to make this work, but it's not really the correct way to animate a property.

The correct way is to change the property on your model layer, then apply the animation.

// Change the model layer's property first.
circle.strokeEnd = endAngle;

// Then apply the animation.
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration            = timeInSeconds;
drawAnimation.fromValue = [NSNumber numberWithFloat:startAngle];
drawAnimation.toValue   = [NSNumber numberWithFloat:endAngle];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];

This is explained in the Core Animation Essentials video from WWDC 2011. I highly recommend watching it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文