本文参考自:http://blog.csdn.net/totogo2010/article/details/8606089,尊重原创!又做了点自己的加工,最终实现了一个小人追这个豆子跑的动画,可随时暂停、继续。
效果如下:
实现该动画的思路很简单:pacman的开口,闭口,以及pacman的行走路径。至于开口、闭口之间的效果并不需要我么实现,插值计算会自动补全动画的。而动画的暂停、继续我们在ios动画系列三这篇文章中已经讲过了,苹果给的有例子。
直接附上代码:
1 // 2 // PacmanViewController.h 3 // AnimationDemo 4 // 5 // Created by yuqiu on 13-7-23. 6 // Copyright (c) 2013年 rongfzh. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 #import <QuartzCore/QuartzCore.h> 11 @interface PacmanViewController : UIViewController 12 { 13 UIBezierPath *_pacmanOpenPath; 14 UIBezierPath *_pacmanClosedPath; 15 CAShapeLayer *_shapeLayer; 16 CAShapeLayer *_ballLayer; 17 UIBezierPath *_ballPath; 18 } 19 @end
1 // 2 // PacmanViewController.m 3 // AnimationDemo 4 // 5 // Created by yuqiu on 13-7-23. 6 // Copyright (c) 2013年 rongfzh. All rights reserved. 7 // 8 9 #import "PacmanViewController.h" 10 #define DEGREES_TO_RADIANS(x) (3.14159265358979323846 * x / 180.0) 11 12 @interface PacmanViewController () 13 14 @end 15 16 @implementation PacmanViewController 17 - (void)viewDidLoad 18 { 19 [super viewDidLoad]; 20 UIButton *btn = [[UIButton alloc]init]; 21 [btn setTitle:@"暂停" forState:UIControlStateNormal]; 22 btn.frame = CGRectMake(10, 400, 145, 40); 23 btn.backgroundColor = [UIColor greenColor]; 24 [btn addTarget:self action:@selector(pauseLayer) forControlEvents:UIControlEventTouchUpInside]; 25 [self.view addSubview:btn]; 26 27 [super viewDidLoad]; 28 UIButton *btn1 = [[UIButton alloc]init]; 29 [btn1 setTitle:@"继续" forState:UIControlStateNormal]; 30 btn1.frame = CGRectMake(160, 400, 145, 40); 31 btn1.backgroundColor = [UIColor greenColor]; 32 [btn1 addTarget:self action:@selector(resumeLayer) forControlEvents:UIControlEventTouchUpInside]; 33 [self.view addSubview:btn1]; 34 35 36 self.view.backgroundColor = [UIColor yellowColor]; 37 38 CGFloat radius = 30.0f;//半径 39 CGFloat diameter = radius * 2;//直径 40 CGPoint arcCenter = CGPointMake(radius, radius);//中心点坐标 41 42 // Create a UIBezierPath for Pacman's open state 43 //以某个点为中心画弧线 创建pacman的开口路径 44 _pacmanOpenPath = [UIBezierPath bezierPathWithArcCenter:arcCenter //弧线中心点的坐标 45 radius:radius //弧线所在圆的半径 46 startAngle:DEGREES_TO_RADIANS(35) //弧线开始的角度值 47 endAngle:DEGREES_TO_RADIANS(325) //弧线结束的角度值 48 clockwise:YES]; //是否顺时针画弧线 49 50 [_pacmanOpenPath addLineToPoint:arcCenter]; 51 [_pacmanOpenPath closePath]; 52 53 // Create a UIBezierPath for Pacman's close state 54 // 创建pacman的闭口路径 55 _pacmanClosedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter 56 radius:radius 57 startAngle:DEGREES_TO_RADIANS(0) 58 endAngle:DEGREES_TO_RADIANS(360) 59 clockwise:YES]; 60 [_pacmanClosedPath addLineToPoint:arcCenter]; 61 [_pacmanClosedPath closePath]; 62 63 // Create a CAShapeLayer for Pacman, fill with yellow 64 //创建这个Pacman的实体,目前还不知道这是怎么创建的??????? 65 _shapeLayer = [CAShapeLayer layer]; 66 _shapeLayer.path = _pacmanClosedPath.CGPath;//path定义了这个shape渲染的范围 67 _shapeLayer.fillColor = [UIColor greenColor].CGColor;//整个shape的填充色 68 _shapeLayer.strokeColor = [UIColor grayColor].CGColor;//画笔的颜色,即边界线的颜色 69 _shapeLayer.lineWidth = 1.0f;//layer边界线宽 70 //_shapeLayer.bounds = CGRectMake(0, 0, diameter, diameter);//layer的边界大小 71 _shapeLayer.position = CGPointMake(0, 40);//layer在它的superLayer上的位置 72 // _shapeLayer.frame = CGRectMake(0, 40, diameter, diameter); 73 [self.view.layer addSublayer:_shapeLayer]; 74 75 //创建一个球球 76 _ballPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(10,0) radius:10 startAngle:DEGREES_TO_RADIANS(0) endAngle:DEGREES_TO_RADIANS(360) clockwise:YES]; 77 _ballLayer = [CAShapeLayer layer]; 78 _ballLayer.fillColor = [UIColor redColor].CGColor; 79 _ballLayer.path = _ballPath.CGPath; 80 _ballLayer.position = CGPointMake(60,70); 81 [self.view.layer addSublayer:_ballLayer]; 82 83 UIGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startAnimation)]; 84 [self.view addGestureRecognizer:recognizer]; 85 } 86 87 - (void)startAnimation { 88 // 创建咬牙动画 89 CABasicAnimation *chompAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 90 chompAnimation.duration = 0.25; 91 chompAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 92 chompAnimation.repeatCount = HUGE_VALF;//无穷大 93 chompAnimation.autoreverses = YES; 94 // Animate between the two path values 95 chompAnimation.fromValue = (id)_pacmanClosedPath.CGPath; 96 chompAnimation.toValue = (id)_pacmanOpenPath.CGPath; 97 [_shapeLayer addAnimation:chompAnimation forKey:@"chompAnimation"]; 98 99 // Create digital '2'-shaped path 100 //创建pacman走的路径 101 UIBezierPath *path = [UIBezierPath bezierPath]; 102 [path moveToPoint:CGPointMake(30, 40)]; 103 [path addLineToPoint:CGPointMake(280, 40)]; 104 [path addLineToPoint:CGPointMake(280, 180)]; 105 [path addLineToPoint:CGPointMake(60,180)]; 106 [path addLineToPoint:CGPointMake(60, 300)]; 107 [path addLineToPoint:CGPointMake(300, 300)]; 108 109 //行走动画 110 CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 111 moveAnimation.repeatCount = HUGE_VALF; 112 moveAnimation.path = path.CGPath; 113 moveAnimation.duration = 6.0f; 114 // Setting the rotation mode ensures Pacman's mouth is always forward. This is a very convenient CA feature. 115 moveAnimation.rotationMode = kCAAnimationRotateAuto; 116 [_shapeLayer addAnimation:moveAnimation forKey:@"moveAnimation"]; 117 118 //创建ball走的路径å 119 UIBezierPath *path1 = [UIBezierPath bezierPath]; 120 [path1 moveToPoint:CGPointMake(30, 70)]; 121 [path1 addLineToPoint:CGPointMake(270, 70)]; 122 [path1 addLineToPoint:CGPointMake(270, 170)]; 123 [path1 addLineToPoint:CGPointMake(30,170)]; 124 [path1 addLineToPoint:CGPointMake(30, 330)]; 125 [path1 addLineToPoint:CGPointMake(300, 330)]; 126 127 CAKeyframeAnimation *moveAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 128 moveAnimation1.repeatCount = HUGE_VALF; 129 moveAnimation1.path = path1.CGPath; 130 moveAnimation1.duration = 5.5f; 131 moveAnimation.rotationMode = kCAAnimationRotateAuto; 132 133 [_ballLayer addAnimation:moveAnimation1 forKey:@"moveAnimation"]; 134 } 135 136 //暂停动画 137 -(void)pauseLayer 138 { 139 CFTimeInterval pausedTime = [self.view.layer convertTime:CACurrentMediaTime() fromLayer:nil]; 140 self.view.layer .speed = 0.0; 141 self.view.layer .timeOffset = pausedTime; 142 } 143 144 //继续动画 145 -(void)resumeLayer 146 { 147 CFTimeInterval pausedTime = [self.view.layer timeOffset]; 148 self.view.layer.speed = 1.0; 149 self.view.layer.timeOffset = 0.0; 150 self.view.layer.beginTime = 0.0; 151 CFTimeInterval timeSincePause = [self.view.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; 152 self.view.layer.beginTime = timeSincePause; 153 } 154 155 - (void)didReceiveMemoryWarning 156 { 157 [super didReceiveMemoryWarning]; 158 // Dispose of any resources that can be recreated. 159 } 160 161 @end
代码中的注释非常清楚,就不再解释了。只再说一点:moveAnimation.rotationMode = kCAAnimationRotateAuto;这句话保证了pacman的嘴巴总是我们想要的方向。
这个动画做的很粗糙,ball的行走路径和pacman的嘴巴有时候都不在一条线上,也不是我预期想要的pacman和ball总是隔固定的大小。这两个没有符合预期的效果,也是我在做这个动画时碰到过的问题。
1、pacman的行走路径,是以pacman的哪个点来看的?2、pacman和ball走的路径不一样长,怎么保证总是隔固定大小?
第一个问题:经过试验,我发觉是以pacman圆上的最上面的点为基准的,即使翻转,依然是以那个点为基准。
第二个问题:利用beginTime,设不同的开始时间,还木有尝试。
好啦,动画系列就告一段落啦!在下个阶段,我将会学习不同格式图片的压缩、处理效率。