CAShapeLayer Animating Path Glitches / Flickers (From Ellipse to Rect and back)
Asked Answered
A

2

8

I am running into an issue when I create an explicit animation to change the value of a CAShapeLayer's path from an ellipse to a rect.

In my canvas controller I setup a basic CAShapeLayer and add it to the root view's layer:

CAShapeLayer *aLayer;
aLayer = [CAShapeLayer layer];
aLayer.frame = CGRectMake(100, 100, 100, 100);
aLayer.path = CGPathCreateWithEllipseInRect(aLayer.frame, nil);
aLayer.lineWidth = 10.0f;
aLayer.strokeColor = [UIColor blackColor].CGColor;
aLayer.fillColor = [UIColor clearColor].CGColor;
[self.view.layer addSublayer:aLayer];

Then, when I animate the path I get a strange glitch / flicker in the last few frames of the animation when the shape becomes a rect, and in the first few frames when it animates away from being a rect. The animation is set up as follows:

CGPathRef newPath = CGPathCreateWithRect(aLayer.frame, nil);
[CATransaction lock];
[CATransaction begin];
[CATransaction setAnimationDuration:5.0f];
CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"path"];
ba.autoreverses = YES;
ba.fillMode = kCAFillModeForwards;
ba.repeatCount = HUGE_VALF;
ba.fromValue = (id)aLayer.path;
ba.toValue = (__bridge id)newPath;
[aLayer addAnimation:ba forKey:@"animatePath"];
[CATransaction commit];
[CATransaction unlock];

I have tried many different things like locking / unlocking the CATransaction, playing with various fill modes, etc...

Here's an image of the glitch: http://www.postfl.com/outgoing/renderingglitch.png

A video of what I am experiencing can be found here: http://vimeo.com/37720876

Anthozoan answered 1/3, 2012 at 8:43 Comment(0)
C
5

Unfortunately this is a limitation of the otherwise awesome animatable path property of CAShapeLayers.

Basically it tries to interpolate between the two paths. It hits trouble when the destination path and start path have a different number of control points - and curves and straight edges will have this problem.

You can try to minimise the effect by drawing your ellipse as 4 curves instead of a single ellipse, but it still isn't quite right. I haven't found a way to go smoothly from curves to polygons.

You may be able to get most of the way there, then transfer to a fade animation for the last part - this won't look as nice, though.

Catoptrics answered 1/3, 2012 at 8:50 Comment(4)
Between your answer and the one I posted from David Duncan, I have a pretty good sense of what's going on. Hopefully the animatable path property gets better in future releases.Anthozoan
If you do work it out using the arc rectangles approach, please post it here!Catoptrics
I don't know if you've worked on this, or seen any good answers since this post was made. I'm starting to work on a general circle to polygon animation, and currently have it working for a circle to square animation. I've posted that code as an answer to this question, #28437514Sulfide
@Sulfide no I haven't worked on this for a while. It ought to be easier than it is...Catoptrics
A
8

I received this feedback from the quartz-dev list:

David Duncan wrote:

Animating the path of a shape layer is only guaranteed to work when you are animating from like to like. A rectangle is a sequence of lines, while an ellipse is a sequence of arcs (you can see the sequence generated by using CGPathApply), and as such the animation between them isn't guaranteed to look very good, or work well at all.

To do this, you basically have to create an analog of a rectangle by using the same curves that you would use to create an ellipse, but with parameters that would cause the rendering to look like a rectangle. This shouldn't be too difficult (and again, you can use what you get from CGPathApply on the path created with CGPathAddEllipseInRect as a guide), but will likely require some tweaking to get right.

Anthozoan answered 1/3, 2012 at 19:40 Comment(0)
C
5

Unfortunately this is a limitation of the otherwise awesome animatable path property of CAShapeLayers.

Basically it tries to interpolate between the two paths. It hits trouble when the destination path and start path have a different number of control points - and curves and straight edges will have this problem.

You can try to minimise the effect by drawing your ellipse as 4 curves instead of a single ellipse, but it still isn't quite right. I haven't found a way to go smoothly from curves to polygons.

You may be able to get most of the way there, then transfer to a fade animation for the last part - this won't look as nice, though.

Catoptrics answered 1/3, 2012 at 8:50 Comment(4)
Between your answer and the one I posted from David Duncan, I have a pretty good sense of what's going on. Hopefully the animatable path property gets better in future releases.Anthozoan
If you do work it out using the arc rectangles approach, please post it here!Catoptrics
I don't know if you've worked on this, or seen any good answers since this post was made. I'm starting to work on a general circle to polygon animation, and currently have it working for a circle to square animation. I've posted that code as an answer to this question, #28437514Sulfide
@Sulfide no I haven't worked on this for a while. It ought to be easier than it is...Catoptrics

© 2022 - 2024 — McMap. All rights reserved.