How to animate drawing part of CGPath

1.7k views Asked by At

I want to approach the following scenario:

enter image description here

If I draw a rectangle using CGBezierPath and CAShapeLayer like the following:

    CAShapeLayer *layerX = [CAShapeLayer layer];
    layerX.path = path.CGPath;

    layerX.lineWidth   = 3;
    layerX.strokeColor = [[UIColor whiteColor] CGColor];
    layerX.fillColor   = [[UIColor clearColor] CGColor];

    [self.view.layer addSublayer: layerX];

And I want to add animation like the image I attached, this cleared area keeps moving around the rectangle path so it gives visual effect of the rectangle being drawn over and over. [Snake movement in old snake games]

I tried animating using CABasicAnimation but I literally couldn't achieve anything, thanks in advance.

3

There are 3 answers

1
Dixit Akabari On

Try this code may be helpful.

    UIBezierPath *drawablePath = [UIBezierPath bezierPathWithRect:CGRectMake(100.0, 100.0, 150.0, 100.0)];
    CAShapeLayer *squareLayer = [[CAShapeLayer alloc] init];
    squareLayer.path = drawablePath.CGPath;
    squareLayer.strokeColor = [UIColor redColor].CGColor;
    squareLayer.lineWidth = 5.f;
    squareLayer.fillColor = [UIColor clearColor].CGColor;
    squareLayer.strokeEnd = 1.f;
    //squareLayer.strokeEnd = 0.9; // this line use draw half line but some animation issue.
    [self.view.layer addSublayer:squareLayer];

    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    drawAnimation.fromValue = (id)[NSNumber numberWithFloat:0.10];
    drawAnimation.toValue = (id)[NSNumber numberWithFloat:1.f];
    drawAnimation.duration = 5.f;
    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    [squareLayer addAnimation:drawAnimation forKey:@"drawRectStroke"];

This code is use to draw rectangle with animation.

1
Ivan On

You have to animate both: strokeStart and strokeEnd and use a CAAnimationGroup to make them happen at the same time.

I found this link which does something similar but in swift. I think it might help.

I will try to implement it if you can't do it. But I can't right now.

Happy coding.

0
stevex On
    let drawablePath = UIBezierPath(rect: CGRect(x: 100, y: 100, width: 150, height: 150))
    let squareLayer = CAShapeLayer()
    squareLayer.path = drawablePath.cgPath;
    squareLayer.strokeColor = UIColor.red.cgColor;
    squareLayer.lineWidth = 5;
    squareLayer.fillColor = UIColor.clear.cgColor;
    squareLayer.strokeEnd = 1;
    //squareLayer.strokeEnd = 0.9; // this line use draw half line but some animation issue.
    flowerView.layer.addSublayer(squareLayer)

    let drawAnimation = CABasicAnimation(keyPath: "strokeEnd")
    drawAnimation.fromValue = 0.1
    drawAnimation.toValue = 1.0
    drawAnimation.duration = 5
    drawAnimation.timingFunction = CAMediaTimingFunction(name:.linear)
    squareLayer.add(drawAnimation, forKey:"drawRectStroke")

Not really an answer to the original question but here's a Swift 5 version of Dixit Akabari's answer, which was useful in itself in that it demonstrates how to animate drawing a UIBezierPath by animating strokeEnd.