How to shift shape (from oval to rect and vice versa) animated?
Dirty code:
UIBezierPath *roundedRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:newRect cornerRadius:10];
UIBezierPath *ovalBezierPath = [UIBezierPath bezierPathWithOvalInRect:newRect];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.duration = 3;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
if (isRect) {
self.shapeLayer.path = roundedRectBezierPath.CGPath;
animation.fromValue = (__bridge id)(ovalBezierPath.CGPath);
animation.toValue = (__bridge id)(roundedRectBezierPath.CGPath);
} else {
self.shapeLayer.path = ovalBezierPath.CGPath;
animation.fromValue = (__bridge id)(roundedRectBezierPath.CGPath);
animation.toValue = (__bridge id)(ovalBezierPath.CGPath);
}
[self.shapeLayer addAnimation:animation forKey:@"animatePath"];
The result is weird:
I expect shape to shrink/expand, not weird redraw.
If you look at the documentation this is exactly the behavior that you should expect. From the docs:
If the two paths have a different number of control points or segments the results are undefined.
You can get around this in two ways: either
For the first option I would use addArcWithCenter:radius:startAngle:endAngle:clockwise:
four times to make up the rounded rect. (It will automatically add the straight lines to your path). You can read more about the construction of Bézier paths in "Thinking like Bézier paths" (written by me). There are some interactive elements there that should help you figure out how adding arcs to a path works.
The other option is to create the paths any way you want with different numbers of control points and/or segments and do the animation yourself. This is an excellent explanation of how to do your own path animations with shape layers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With