Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animation of masked UIView, CALayer

I am trying to achieve the following: The user taps on a view, a circular view pops up to the left of it with some image content in it. The view should animate in starting from the point of touch to the final frame which is outside the touched view and to the left. During the animation it should be a circle, growing into the right position and size

All works well with the code below, only that during the animation, circular boundary is only on the left. It's like the CALayer shape is sliding into its final frame.

It looks sort of like this.

enter image description here

Once the animation completes, I have the full circle as expected.

CGFloat w = 300;
CGRect frame = CGRectMake(myX, myY, w, w);
CGPoint p = [touch locationInView:self.imageView];
CGRect initialFrame = CGRectMake(p.x, p.y, 0,0);
UIImageView *circle = [[UIImageView alloc] initWithFrame:frame];
circle.image = [UIImage imageNamed:@"china"];
circle.contentMode = UIViewContentModeScaleAspectFill;
circle.backgroundColor = [UIColor clearColor];
circle.layer.borderWidth = 1;
circle.layer.borderColor = [UIColor grayColor].CGColor;
circle.layer.masksToBounds = YES;

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = CGRectMake(0, 0, w, w);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, maskRect);
maskLayer.path = path;
CGPathRelease(path);
circle.layer.mask = maskLayer;

circle.frame = initialFrame;
[self.imageView addSubview:circle];
[UIView animateWithDuration:1.0 animations:^{
    circle.frame = frame;
}];

I have tried just working with the cornerRadius of the CALayer, but that does not lead to satisfactory results either, as the radius would have to change with the frame size as well.

like image 348
Mundi Avatar asked Sep 24 '12 11:09

Mundi


1 Answers

You are animating the frame but not the mask. The circular mask remains constant in size and your image frame is animated from the top left to the finale full size. That is why you get the circular clipping of the top left part of the image, until it gets to the finale frame size.

This is what basically happens in your animation: enter image description here

You can try to animate a transform (which will transform the finale clipped image exactly as you want it to look) instead of animating the frame.

Something like:

// Don't animate the frame. Give it the finale value before animation.
circle.frame = frame;

// Animate a transform instead. For example, a scaling transform.
circle.transform = CGAffineTransformMakeScale(0, 0);
[UIView animateWithDuration:1.0 animations:^{
    circle.transform = CGAffineTransformMakeScale(1, 1);
}];
like image 115
PostPCDev Avatar answered Oct 16 '22 08:10

PostPCDev