简体   繁体   中英

Animate a UIBezierPath which clips an UIImage

I have an image that looks like a donut and want to animate it so that it looks like the donut circle is not completed (stroke is not closed). It is hard to describe but imagine a speedometer which goes to 100 and you drive 50. I have done the masking with the help of a path and [path addClip] inside UIGraphicsBeginImageContextWithOptions where I also render the UIImage.

My question now is can I or how can I animate the path. I tried it with a CABasicAnimation and 2 paths (the first path where startAngle and endAngle are the same and the second path were endAngle is the desired angle) with "path" as keyPath but that is not working.

Anything helps ;)

I would suggest setting up a CAShapeLayer, and letting the shape layer render your donut shape. You should be able to render your donut shape as a CGPath of an arc with a thick line.

CAShapeLayer has strokeStart and strokeEnd properties. Both range from 0.0 to 1.0. By default, strokeStart is 0.0 (start at the beginning) and strokeEnd is 1.0 (draw the entire path). These properties are animatable.

If you change the strokeEnd from .75 to 1.0 then your path will start out with only 3/4 of it drawn, and animate drawing the last 1/4 of the path.

I have a project on gitHub that illustrates using a shape layer as a mask on an image in order to create a "clock wipe" transition. For that, I make the line width on my arc so large that the shape completely fills the frame rectangle instead of drawing a donut shape. In your case, you'd make the line thickness less so it draws your donut.

Core Animation demo on Github

Click the "Mask Animation" button in the app to see the shape layer animation at work.

I animate UIBezierPath using CABasicAnimation using...

UIBezierPath *bezierPath = [self bezierPath];

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

bezierLayer.path = bezierPath.CGPath;
bezierLayer.strokeColor = [UIColor redColor].CGColor;
bezierLayer.fillColor = [UIColor clearColor].CGColor;
bezierLayer.lineWidth = 5.0;
bezierLayer.strokeStart = 0.0;
bezierLayer.strokeEnd = 1.0;
[self.view.layer addSublayer:bezierLayer];

if (animate)
{
    CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animateStrokeEnd.duration = 1.0;
    animateStrokeEnd.fromValue = @0.0f;
    animateStrokeEnd.toValue = @1.0f;
    [bezierLayer addAnimation:animateStrokeEnd forKey:@"strokeEndAnimation"];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM