Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate a scale on a circle to keep centerposition

How can I make a circle animate scaling but keep the centerposition of the circle in the same point. This code makes the center of the circle move down and right, seems like its bound in top and left corner by the frame.

This layer is as you can see a mask on another layer.

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, CGRectMake(400, 400, 1000, 1000));

CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
[shapeLayer setPath:path];
[shapeLayer setFrame:[glView frame]];
[shapeLayer setFillColor:[[UIColor blackColor] CGColor]];

[[glView layer] setMask:shapeLayer];

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.0, 0.0, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
animation.repeatCount = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 3;
[shapeLayer addAnimation:animation forKey:@"transform.scale"];
like image 593
einarnot Avatar asked Dec 14 '11 08:12

einarnot


2 Answers

A layer is scaled around its anchor point, which by default is the center of the layer's frame. This is explained in Core Animation Programming Guide - Specifying a Layer's Geometry.

Your problem is that your circle's center is not at the same point as your layer's anchor point.

So one way to fix your problem is to move shapeLayer.anchorPoint to be the same as the circle's center, like this:

CGRect circleFrame = CGRectMake(400, 400, 1000, 1000);
CGPoint circleAnchor = CGPointMake(CGRectGetMidX(circleFrame) / CGRectGetMaxX(circleFrame),
    CGRectGetMidY(circleFrame) / CGRectGetMaxY(circleFrame));
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:circleFrame];

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
shapeLayer.anchorPoint = circleAnchor;
shapeLayer.frame = glView.frame;
shapeLayer.fillColor = [UIColor blackColor].CGColor;

glView.layer.mask = shapeLayer;
// and then your animation code

You want to set the anchor point before you set the frame, because setting the anchor point after setting the frame will change the frame.

like image 126
rob mayoff Avatar answered Nov 04 '22 12:11

rob mayoff


These are guesses, not able to try myself at the moment:

  • Set shapeLayer's frame to glView's bounds, not frame as it should be in the coordinate system of the view it belongs to, not the superview.
  • Set shapeLayer's anchorPoint to 0.5,0.5 - this is the default for a CALayer (meaning the centre of the layer) but from what you are describing this is not the case for your shape layer - unless the frame/bounds thing is causing the issue.
like image 42
jrturton Avatar answered Nov 04 '22 13:11

jrturton