原文:
http://nachbaur.com/blog/core-animation-part-1
sample下载地址
http://nachbaur.com/wp-content/uploads/2011/01/CALayerAnimTest.zip
共描述了4个动画
1)轨道环绕,比如月球绕地球
源码:
self.view.backgroundColor = [UIColor blackColor];
// Orbit #1
CALayer *orbit1 = [CALayer layer];
orbit1.bounds = CGRectMake(0, 0, 200, 200);
orbit1.position = self.view.center;
orbit1.cornerRadius = 100;
orbit1.borderColor = [UIColor redColor].CGColor;
orbit1.borderWidth = 1.5;
CALayer *planet1 = [CALayer layer];
planet1.bounds = CGRectMake(0, 0, 20, 20);
planet1.position = CGPointMake(100, 0);
planet1.cornerRadius = 10;
planet1.backgroundColor = [UIColor redColor].CGColor;
[orbit1 addSublayer:planet1];
CABasicAnimation *anim1 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
anim1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim1.fromValue = [NSNumber numberWithFloat:0];
anim1.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
anim1.repeatCount = HUGE_VALF;
anim1.duration = 8.0;
[orbit1 addAnimation:anim1 forKey:@"transform"];
[self.view.layer addSublayer:orbit1];
// Orbit #2
CALayer *orbit2 = [CALayer layer];
orbit2.bounds = CGRectMake(0, 0, 120, 120);
orbit2.position = planet1.position;
orbit2.cornerRadius = 60;
orbit2.borderColor = [UIColor blueColor].CGColor;
orbit2.borderWidth = 1.5;
CALayer *planet2 = [CALayer layer];
planet2.bounds = CGRectMake(0, 0, 16, 16);
planet2.position = CGPointMake(60, 0);
planet2.cornerRadius = 8;
planet2.backgroundColor = [UIColor blueColor].CGColor;
[orbit2 addSublayer:planet2];
CABasicAnimation *anim2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
anim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim2.fromValue = [NSNumber numberWithFloat:0];
anim2.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
anim2.repeatCount = HUGE_VALF;
anim2.duration = 4.0;
[orbit2 addAnimation:anim2 forKey:@"transform"];
[orbit1 addSublayer:orbit2];
// Orbit #3
CALayer *orbit3 = [CALayer layer];
orbit3.bounds = CGRectMake(0, 0, 72, 72);
orbit3.position = planet2.position;
orbit3.cornerRadius = 36;
orbit3.borderColor = [UIColor grayColor].CGColor;
orbit3.borderWidth = 1.5;
CALayer *planet3 = [CALayer layer];
planet3.bounds = CGRectMake(0, 0, 12, 12);
planet3.position = CGPointMake(36, 0);
planet3.cornerRadius = 6;
planet3.backgroundColor = [UIColor grayColor].CGColor;
[orbit3 addSublayer:planet3];
CABasicAnimation *anim3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
anim3.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim3.fromValue = [NSNumber numberWithFloat:0];
anim3.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
anim3.repeatCount = HUGE_VALF;
anim3.duration = 2.0;
[orbit3 addAnimation:anim3 forKey:@"transform"];
[orbit2 addSublayer:orbit3];
2。飘动的云
源码
UIImage *cloudImage = [UIImage imageNamed:@"cloud.png"];
CALayer *cloud = [CALayer layer];
cloud.contents = (id)cloudImage.CGImage;
cloud.bounds = CGRectMake(0, 0, cloudImage.size.width, cloudImage.size.height);
cloud.position = CGPointMake(self.view.bounds.size.width / 2,
cloudImage.size.height / 2);
[self.view.layer addSublayer:cloud];
CGPoint startPt = CGPointMake(self.view.bounds.size.width + cloud.bounds.size.width / 2,
cloud.position.y);
CGPoint endPt = CGPointMake(cloud.bounds.size.width / -2,
cloud.position.y);
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
anim.fromValue = [NSValue valueWithCGPoint:startPt];
anim.toValue = [NSValue valueWithCGPoint:endPt];
anim.repeatCount = HUGE_VALF;
anim.duration = 8.0;
[cloud addAnimation:anim forKey:@"position"];
3。点击后放大又缩小的button, 以及点击后飘动的东西,比如删除时,将文件飘到垃圾箱
源码
- (void)loadView {
[super loadView];
self.view.backgroundColor = [UIColor whiteColor];
UIScrollView *scrollView = [[[UIScrollView alloc] initWithFrame:self.view.bounds] autorelease];
scrollView.bounces = YES;
[self.view addSubview:scrollView];
// Scale out on click
{
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 320, 24)] autorelease];
label.text = @"Scale button";
label.textAlignment = UITextAlignmentCenter;
[label sizeToFit];
[scrollView addSubview:label];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.center = CGPointMake(220, 30);
button.tag = ButtonActionsBehaviorTypeExpand;
[button setTitle:@"Delete" forState:UIControlStateNormal];
[button sizeToFit];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
}
// Animated trash delete
{
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(10, 126, 320, 24)] autorelease];
label.text = @"Animate image into trash button";
label.textAlignment = UITextAlignmentCenter;
[label sizeToFit];
[scrollView addSubview:label];
UIImageView *icon = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"carmodel.png"]] autorelease];
icon.center = CGPointMake(290, 150);
icon.tag = ButtonActionsBehaviorTypeAnimateTrash;
[scrollView addSubview:icon];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.center = CGPointMake(40, 200);
button.tag = ButtonActionsBehaviorTypeAnimateTrash;
[button setTitle:@"Delete Icon" forState:UIControlStateNormal];
[button sizeToFit];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
[scrollView bringSubviewToFront:icon];
}
// Determine the size of all subviews of the scrollview
CGRect contentSize = CGRectZero;
for (UIView *subview in scrollView.subviews) {
contentSize = CGRectUnion(contentSize, subview.frame);
}
scrollView.contentSize = contentSize.size;
}
- (void)buttonClicked:(id)sender {
UIView *senderView = (UIView*)sender;
if (![senderView isKindOfClass:[UIView class]])
return;
switch (senderView.tag) {
case ButtonActionsBehaviorTypeExpand: {
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.125;
anim.repeatCount = 1;
anim.autoreverses = YES;
anim.removedOnCompletion = YES;
anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)];
[senderView.layer addAnimation:anim forKey:nil];
break;
}
case ButtonActionsBehaviorTypeAnimateTrash: {
UIView *icon = nil;
for (UIView *theview in senderView.superview.subviews) {
if (theview.tag != ButtonActionsBehaviorTypeAnimateTrash)
continue;
if ([theview isKindOfClass:[UIImageView class]]) {
icon = theview;
break;
}
}
if (!icon)
return;
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:icon.center];
[movePath addQuadCurveToPoint:senderView.center
controlPoint:CGPointMake(senderView.center.x, icon.center.y)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
scaleAnim.removedOnCompletion = YES;
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:@"alpha"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.1];
opacityAnim.removedOnCompletion = YES;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, scaleAnim, opacityAnim, nil];
animGroup.duration = 0.5;
[icon.layer addAnimation:animGroup forKey:nil];
break;
}
}
}
4。汽车沿着跑道跑
源码:
#define degreesToRadians(x) (M_PI * x / 180.0)
#define P(x,y) CGPointMake(x, y)
@implementation RaceTrackViewController
- (void)loadView {
[super loadView];
self.view.backgroundColor = [UIColor greenColor];
UIBezierPath *trackPath = [UIBezierPath bezierPath];
[trackPath moveToPoint:P(160, 25)];
[trackPath addCurveToPoint:P(300, 120)
controlPoint1:P(320, 0)
controlPoint2:P(300, 80)];
[trackPath addCurveToPoint:P(80, 380)
controlPoint1:P(300, 200)
controlPoint2:P(200, 480)];
[trackPath addCurveToPoint:P(140, 300)
controlPoint1:P(0, 300)
controlPoint2:P(200, 220)];
[trackPath addCurveToPoint:P(210, 200)
controlPoint1:P(30, 420)
controlPoint2:P(280, 300)];
[trackPath addCurveToPoint:P(70, 110)
controlPoint1:P(110, 80)
controlPoint2:P(110, 80)];
[trackPath addCurveToPoint:P(160, 25)
controlPoint1:P(0, 160)
controlPoint2:P(0, 40)];
CAShapeLayer *racetrack = [CAShapeLayer layer];
racetrack.path = trackPath.CGPath;
racetrack.strokeColor = [UIColor blackColor].CGColor;
racetrack.fillColor = [UIColor clearColor].CGColor;
racetrack.lineWidth = 30.0;
[self.view.layer addSublayer:racetrack];
CAShapeLayer *centerline = [CAShapeLayer layer];
centerline.path = trackPath.CGPath;
centerline.strokeColor = [UIColor whiteColor].CGColor;
centerline.fillColor = [UIColor clearColor].CGColor;
centerline.lineWidth = 2.0;
centerline.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:6], [NSNumber numberWithInt:2], nil];
[self.view.layer addSublayer:centerline];
CALayer *car = [CALayer layer];
car.bounds = CGRectMake(0, 0, 44.0, 20.0);
car.position = P(160, 25);
car.contents = (id)([UIImage imageNamed:@"carmodel.png"].CGImage);
[self.view.layer addSublayer:car];
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
anim.path = trackPath.CGPath;
anim.rotationMode = kCAAnimationRotateAuto;
anim.repeatCount = HUGE_VALF;
anim.duration = 8.0;
[car addAnimation:anim forKey:@"race"];
}