einarnot
einarnot

Reputation: 565

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"];

Upvotes: 9

Views: 7474

Answers (2)

rob mayoff
rob mayoff

Reputation: 385750

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.

Upvotes: 6

jrturton
jrturton

Reputation: 119262

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.

Upvotes: 3

Related Questions