Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate arc/donut segment stroke and length change

sketch

I need to animate arcs (a.k.a donut segments) in the following scenarios where the arc maintains a constant radius r to the imaginary circle center (the arc sits right outside the circle).

1) Animate the arc stroke width from x to y, while maintaining a radius r and angle alpha.

2) Animate the arc angle from alpha to beta while maintaining a constant stroke width and radius.

3) do 1 and 2 together but possibly with independent animations/timings.

Here's what I have so far:

I’ve implemented the arc drawing as a custom view that simply draws the arc with CGContextAddArc. This is fine for a static arc but it doesn’t animate anything.

Also, I know how to draw clipped images with things like [UIBezierPath addClip].

The latter is interesting because I think that for scenario 1, I can achieve the desired effect in two ways: either keep drawing an arc and modify both stroke and radius to maintain the same perceived inner circle radius (which I’m not optimistic about, I’m afraid that the radius will “jiggle”), or draw a segment of a circle that grows in size (maybe by simply modifying the scale with an affine transform) and is then clipped by a static circular mask.

Now, how do I take all these concepts and nail them down into some actual drawing code? I don’t need real code (though that would be fine too), but more like a conceptual approach, like, can I do this all with a UIView with custom drawing, or do we need to talk about custom key animations that I understand involve CALayers and such. In other words, what’s the right architecture to do all this that would be easiest to code while being efficient from a compositing perspective for smooth animation?

like image 511
Jaanus Avatar asked Jun 07 '12 06:06

Jaanus


2 Answers

You can already do this with a CAShapeLayer by creating the path for the arc and then animate different stroke properties. You could create the path for the full circle and use the strokeStart and strokeEnd properties to only stroke a certain part of the circle. It is worth noting that the shape layer is center stroked so they increase equally inwards and outwards as you increase the line width. To counter this you could either mask it with the same circle shape and double the line width or animate the path so that the radius increases by half of the line width increase so that the inner most point has the same distance to the center at all times.

The first example can be done by animating the lineWidth property and the second can be done by animating the strokeStart and strokeEnd properties

like image 191
David Rönnqvist Avatar answered Sep 29 '22 13:09

David Rönnqvist


You should implement this using custom animatable properties on a CALayer subclass. This tutorial (with source here) is for creating animated pie charts and looks pretty good. You should be able to modify it for your requirements.

like image 31
jrturton Avatar answered Sep 29 '22 13:09

jrturton