Reputation: 9740
I am setting a mask with all rounded corners path to a view like this:
CGFloat cornerRadius = CGRectGetHeight(self.myView.bounds) / 2;
CGSize cornerRadiusSize = CGSizeMake(cornerRadius, cornerRadius);
CGRect bounds = self.myView.bounds;
CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:cornerRadiusSize];
maskLayer.path = maskPath.CGPath;
self.myView.layer.mask = maskLayer;
that looks like this:
I am trying to animate it to a path with top left and top right rounded corners like this:
UIBezierPath *newMaskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:cornerRadiusSize];
CABasicAnimation *maskPathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
maskPathAnimation.duration = 0.3;
maskPathAnimation.fromValue = (id)maskLayer.path;
maskPathAnimation.toValue = (id)newMaskPath.CGPath;
[maskLayer addAnimation:maskPathAnimation forKey:nil];
maskLayer.path = newMaskPath.CGPath;
that looks like this:
But the animation is mangled, it looks like it animates some corners to other corners:
Upvotes: 1
Views: 473
Reputation: 9740
I solved it by creating the mask paths by hand using this method:
- (UIBezierPath *)getMaskPathForView:(UIView *)view withCorners:(UIRectCorner)corners {
CGSize size = view.bounds.size;
CGFloat cornerRadius = size.height / 2;
UIBezierPath *maskPath = [UIBezierPath bezierPath];
// top left
if (corners & UIRectCornerTopLeft) {
[maskPath moveToPoint:CGPointMake(0, cornerRadius)];
[maskPath addQuadCurveToPoint:CGPointMake(cornerRadius, 0) controlPoint:CGPointZero];
} else {
CGPoint topLeftCornerPoint = CGPointZero;
[maskPath moveToPoint:topLeftCornerPoint];
[maskPath addQuadCurveToPoint:topLeftCornerPoint controlPoint:topLeftCornerPoint];
}
// top right
if (corners & UIRectCornerTopRight) {
[maskPath addLineToPoint:CGPointMake(size.width - cornerRadius, 0)];
[maskPath addQuadCurveToPoint:CGPointMake(size.width, cornerRadius) controlPoint:CGPointMake(size.width, 0)];
} else {
CGPoint topRightCornerPoint = CGPointMake(size.width, 0);
[maskPath addLineToPoint:topRightCornerPoint];
[maskPath addQuadCurveToPoint:topRightCornerPoint controlPoint:topRightCornerPoint];
}
// bottom right
if (corners & UIRectCornerBottomRight) {
[maskPath addLineToPoint:CGPointMake(size.width, size.height - cornerRadius)];
[maskPath addQuadCurveToPoint:CGPointMake(size.width - cornerRadius, size.height) controlPoint:CGPointMake(size.width, size.height)];
} else {
CGPoint bottomRightCornerPoint = CGPointMake(size.width, size.height);
[maskPath addLineToPoint:bottomRightCornerPoint];
[maskPath addQuadCurveToPoint:bottomRightCornerPoint controlPoint:bottomRightCornerPoint];
}
// bottom left
if (corners & UIRectCornerBottomLeft) {
[maskPath addLineToPoint:CGPointMake(cornerRadius, size.height)];
[maskPath addQuadCurveToPoint:CGPointMake(0, size.height - cornerRadius) controlPoint:CGPointMake(0, size.height)];
} else {
CGPoint bottomLeftCornerPoint = CGPointMake(0, size.height);
[maskPath addLineToPoint:bottomLeftCornerPoint];
[maskPath addQuadCurveToPoint:bottomLeftCornerPoint controlPoint:bottomLeftCornerPoint];
}
[maskPath closePath];
return maskPath;
}
like this:
CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *maskPath = [self getMaskPathForView:self.myView withCorners:UIRectCornerAllCorners];
maskLayer.path = maskPath.CGPath;
self.myView.layer.mask = maskLayer;
and:
UIBezierPath *newMaskPath = [self getMaskPathForView:self.myView withCorners:UIRectCornerTopLeft | UIRectCornerTopRight];
CABasicAnimation *maskPathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
maskPathAnimation.duration = 0.3;
maskPathAnimation.fromValue = (id)maskLayer.path;
maskPathAnimation.toValue = (id)newMaskPath.CGPath;
[maskLayer addAnimation:maskPathAnimation forKey:nil];
maskLayer.path = newMaskPath.CGPath;
Upvotes: 1