yershuachu
yershuachu

Reputation: 788

How to prevent CAShapeLayer from drawing before CABasicAnimation starts

I written "space" separated progress circle in which I animate the progress sequentialy.

Method is being called 3 times with diffrent progress and arc number. The problem is - the BezierPaths draws theirselfs before animation starts and they disappear when it starts giving bad efect.

Is there any way to prevent them from redrawing until animation starts?

- (void)drawArcNo:(NSInteger)number withProgress:(CGFloat)progress
{
    UIBezierPath *bezierPath = [UIBezierPath bezierPath];

    CGFloat angle = (number * 120) - 85;

    [bezierPath addArcWithCenter:CGPointMake(self.circleBackgroundView.bounds.size.width / 2, self.circleBackgroundView.bounds.size.height / 2) radius:50.0 startAngle:degreesToRadians(angle) endAngle:degreesToRadians((angle + 115) * progress) clockwise:YES];

    CAShapeLayer *progressLayer = [[CAShapeLayer alloc] init];

    [progressLayer setPath:bezierPath.CGPath];

    [progressLayer setStrokeColor:[UIColor redColor].CGColor];
    [progressLayer setFillColor:[UIColor clearColor].CGColor];
    [progressLayer setLineWidth:5];

    [progressLayer setStrokeStart:0.0];
    [progressLayer setStrokeEnd:1.0];

    [self.circleBackgroundView.layer addSublayer:progressLayer];

    CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animateStrokeEnd.fillMode = kCAFillModeForwards;
    animateStrokeEnd.removedOnCompletion = NO;
    animateStrokeEnd.beginTime = CACurrentMediaTime() + number;
    animateStrokeEnd.duration  = 1 * progress;  //kAnimationDuration * (90 / 100);
    animateStrokeEnd.fromValue = [NSNumber numberWithFloat:0.0f];
    animateStrokeEnd.toValue   = [NSNumber numberWithFloat:1.0f];
    [progressLayer addAnimation:animateStrokeEnd forKey:[NSString stringWithFormat:@"animateStronke%d", number]];
}

Upvotes: 2

Views: 338

Answers (1)

yershuachu
yershuachu

Reputation: 788

Hotfix for that is:

[self drawArcNo:0 withProgress:progressRatio -= (CGFloat)(1 / 3)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self drawArcNo:1 withProgress:progressRatio -= (CGFloat)(1 / 3)];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self drawArcNo:2 withProgress:progressRatio -= (CGFloat)(1 / 3)];
    });
});

but i really don't like this soultion. Working with animation beginTime seem to be very problematic.

UPDATE: Thanks to David Rönnqvist i fixed it:

animateStrokeEnd.fillMode = kCAFillModeBackwards;

Upvotes: 0

Related Questions