I am making an iPhone app that draws a circle on the screen. I use a timer (every 5 second), so that I can 'grow' the circle, then wait 5 seconds then grow again. Now I am having trouble when animating the increase in size of the circle (I use paths and a CAShapeLayer layer). The size (from and to) are fine with the animation, its just when it starts the circle moves to the upper left hand side and grows from there. Any help or suggestions would be great. Thanks
The class where this is implemented is a UIControl, which is added to a UIView.
//Called in init method
(void) initalPop {
//Circle
self.bubble = [CAShapeLayer layer];
self.bubble.bounds = self.bounds;
self.bubble.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
self.bubble.fillColor = [
[UIColor greenColor] CGColor
];
self.bubble.strokeColor = [
[UIColor greenColor] CGColor
];
self.bubble.lineWidth = 4.0;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, self.bounds);
self.bubble.path = path;
[self.layer addSublayer: self.bubble];
}
//Called when timer goes off
- (void) StageGrow {
CGFloat growSize = 50.0;
//Change the size of us and center the circle (but dont want to animate this
[CATransaction begin];
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
self.bounds = CGRectMake(0, 0, self.bounds.size.width + growSize, self.bounds.size.height + growSize);
self.bubble.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
[CATransaction commit];
[self ActualGrowCircle];
} - (void) ActualGrowCircle {
CGMutablePathRef oldPath = CGPathCreateMutable();
CGPathAddEllipseInRect(oldPath, nil, self.bubble.bounds);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, self.bounds);
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath: @"path"];
animation.duration = 2.0;
animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
animation.repeatCount = 1;
animation.delegate = self;
animation.autoreverses = NO;
animation.fromValue = (__bridge id) oldPath;
animation.toValue = (__bridge id) path;
self.bubble.bounds = self.bounds;
self.bubble.path = path;
[self.bubble addAnimation: animation forKey: @"animatePath"];
}
Worked it out. In the long run I grouped the animations together and all became good (see code below). Thanks for your help Rob.
-(void)ActualGrowCircle {
CGMutablePathRef newPath = CGPathCreateMutable();
CGPathAddEllipseInRect(newPath, nil, self.bounds);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.repeatCount = 1;
animation.autoreverses = NO;
animation.fromValue = (__bridge id)self.bubble.path;
animation.toValue = (__bridge id)newPath;
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"bounds"];
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation2.repeatCount = 1;
animation2.autoreverses = NO;
animation2.fromValue = [NSValue valueWithCGRect:self.bubble.bounds];
animation2.toValue = [NSValue valueWithCGRect:self.bounds];
CAAnimationGroup *group = [CAAnimationGroup animation];
[group setAnimations:[NSArray arrayWithObjects: animation2, animation, nil]];
group.duration = 0.5;
group.delegate = self;
self.bubble.bounds = self.bounds;
self.bubble.path = newPath;
[self.bubble addAnimation:group forKey:@"animateGroup"];
CGPathRelease(newPath);
}