码迷,mamicode.com
首页 > 移动开发 > 详细

iOS开发——动画编程OC篇&(三)关键帧动画

时间:2015-06-04 22:18:39      阅读:1518      评论:0      收藏:0      [点我收藏+]

标签:

一、简单介绍

是CApropertyAnimation的子类,跟CABasicAnimation的 区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而 CAKeyframeAnimation会使用一个NSArray保存这些数值

属性解析:

values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧

path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略

keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的

说明:CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation

二、代码示例

第一种方式:

代码:

技术分享
 1 //
 2 //  YYViewController.m
 3 //  10-核心动画(关键帧动画1)
 4 //
 5 //  Created by apple on 14-6-21.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 
11 @interface YYViewController ()
12 @property (weak, nonatomic) IBOutlet UIView *customView;
13 
14 @end
15 
16 @implementation YYViewController
17 
18 
19 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
20 {
21     //1.创建核心动画
22     CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
23     //平移
24     keyAnima.keyPath=@"position";
25     //1.1告诉系统要执行什么动画
26     NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
27     NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 100)];
28     NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(200, 200)];
29     NSValue *value4=[NSValue valueWithCGPoint:CGPointMake(100, 200)];
30     NSValue *value5=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
31     keyAnima.values=@[value1,value2,value3,value4,value5];
32     //1.2设置动画执行完毕后,不删除动画
33     keyAnima.removedOnCompletion=NO;
34     //1.3设置保存动画的最新状态
35     keyAnima.fillMode=kCAFillModeForwards;
36     //1.4设置动画执行的时间
37     keyAnima.duration=4.0;
38     //1.5设置动画的节奏
39     keyAnima.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
40     
41     //设置代理,开始—结束
42     keyAnima.delegate=self;
43     //2.添加核心动画
44     [self.customView.layer addAnimation:keyAnima forKey:nil];
45 }
46 
47 -(void)animationDidStart:(CAAnimation *)anim
48 {
49     NSLog(@"开始动画");
50 }
51 
52 -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
53 {
54     NSLog(@"结束动画");
55 }
56 @end
技术分享

说明:这个项目在storyboard中拖入了一个view,并和控制器中的custom进行了关联。

效果和打印结果:

   技术分享

补充:设置动画的节奏

技术分享

第二种方式(使用path)让layer在指定的路径上移动(画圆):

代码:

技术分享
 1 #import "YYViewController.h"
 2 
 3 @interface YYViewController ()
 4 @property (weak, nonatomic) IBOutlet UIView *customView;
 5 
 6 @end
 7 
 8 @implementation YYViewController
 9 
10 
11 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
12 {
13     //1.创建核心动画
14     CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
15     //平移
16     keyAnima.keyPath=@"position";
17     //1.1告诉系统要执行什么动画
18     //创建一条路径
19     CGMutablePathRef path=CGPathCreateMutable();
20     //设置一个圆的路径
21     CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 100));
22     keyAnima.path=path;
23     
24     //有create就一定要有release
25     CGPathRelease(path);
26     //1.2设置动画执行完毕后,不删除动画
27     keyAnima.removedOnCompletion=NO;
28     //1.3设置保存动画的最新状态
29     keyAnima.fillMode=kCAFillModeForwards;
30     //1.4设置动画执行的时间
31     keyAnima.duration=5.0;
32     //1.5设置动画的节奏
33     keyAnima.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
34     
35     //设置代理,开始—结束
36     keyAnima.delegate=self;
37     //2.添加核心动画
38     [self.customView.layer addAnimation:keyAnima forKey:nil];
39 }
40 
41 -(void)animationDidStart:(CAAnimation *)anim
42 {
43     NSLog(@"开始动画");
44 }
45 
46 -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
47 {
48     NSLog(@"结束动画");
49 }
50 @end
技术分享

说明:可以通过path属性,让layer在指定的轨迹上运动。

停止动画:

技术分享
 1 #import "YYViewController.h"
 2 
 3 @interface YYViewController ()
 4 @property (weak, nonatomic) IBOutlet UIView *customView;
 5 - (IBAction)stopOnClick:(UIButton *)sender;
 6 
 7 @end
 8 
 9 @implementation YYViewController
10 
11 
12 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
13 {
14     //1.创建核心动画
15     CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
16     //平移
17     keyAnima.keyPath=@"position";
18     //1.1告诉系统要执行什么动画
19     //创建一条路径
20     CGMutablePathRef path=CGPathCreateMutable();
21     //设置一个圆的路径
22     CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 100));
23     keyAnima.path=path;
24     
25     //有create就一定要有release
26     CGPathRelease(path);
27     //1.2设置动画执行完毕后,不删除动画
28     keyAnima.removedOnCompletion=NO;
29     //1.3设置保存动画的最新状态
30     keyAnima.fillMode=kCAFillModeForwards;
31     //1.4设置动画执行的时间
32     keyAnima.duration=5.0;
33     //1.5设置动画的节奏
34     keyAnima.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
35     
36     //2.添加核心动画
37     [self.customView.layer addAnimation:keyAnima forKey:@"wendingding"];
38 }
39 
40 - (IBAction)stopOnClick:(UIButton *)sender {
41     //停止self.customView.layer上名称标示为wendingding的动画
42     [self.customView.layer removeAnimationForKey:@"wendingding"];
43 }
44 @end
技术分享

技术分享

点击停止动画,程序内部会调用  [self.customView.layer removeAnimationForKey:@"wendingding"];停止self.customView.layer上名称标示为wendingding的动画。

三、图标抖动

代码示例:

技术分享
 1 //
 2 //  YYViewController.m
 3 //  12-图标抖动
 4 //
 5 //  Created by apple on 14-6-21.
 6 //  Copyright (c) 2014年 itcase. All rights reserved.
 7 //
 8 
 9 #import "YYViewController.h"
10 #define angle2Radian(angle)  ((angle)/180.0*M_PI)
11 
12 @interface YYViewController ()
13 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
14 
15 @end
16 
17 
18 @implementation YYViewController
19 
20 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
21 {
22     //1.创建核心动画
23     CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
24     keyAnima.keyPath=@"transform.rotation";
25     //设置动画时间
26     keyAnima.duration=0.1;
27     //设置图标抖动弧度
28     //把度数转换为弧度  度数/180*M_PI
29     keyAnima.values=@[@(-angle2Radian(4)),@(angle2Radian(4)),@(-angle2Radian(4))];
30     //设置动画的重复次数(设置为最大值)
31     keyAnima.repeatCount=MAXFLOAT;
32     
33     keyAnima.fillMode=kCAFillModeForwards;
34     keyAnima.removedOnCompletion=NO;
35     //2.添加动画
36     [self.iconView.layer addAnimation:keyAnima forKey:nil];
37 }
38 
39 @end
技术分享

说明:图标向左向右偏转一个弧度(4),产生抖动的视觉效果。

程序界面:

技术分享

封装关键字动画:

  1 /*
  2  将动画和图层进行解耦
  3  
  4  1. 给每一个动画方法增加一个返回值,返回对应的关键帧动画或者基本动画
  5  2. 把每一个成员方法,修改为类方法,从 - 变成 + 
  6  */
  7 - (id)initWithFrame:(CGRect)frame
  8 {
  9     self = [super initWithFrame:frame];
 10     if (self) {
 11         self.backgroundColor = [UIColor redColor];
 12     }
 13     return self;
 14 }
 15 
 16 #pragma mark - 私有方法
 17 #pragma mark 生成屏幕上的随机点
 18 + (CGPoint)randomPoint
 19 {
 20     // 获得父视图的大小
 21     CGSize size = [UIScreen mainScreen].applicationFrame.size;
 22     
 23     CGFloat x = arc4random_uniform(size.width);
 24     CGFloat y = arc4random_uniform(size.height);
 25     
 26     return CGPointMake(x, y);
 27 }
 28 
 29 #pragma mark - 关键帧动画方法
 30 /*
 31  在做核心动画是,一定记住动画的效果要是随机的,否则,无论多么绚丽的效果,用户都会审美疲劳!
 32  
 33  因为核心动画做的效果属于装饰性动画,动画过程中不需要用户的交互,因此动画效果就格外重要。
 34  */
 35 // 使用屏幕上的随机点作为中间点,指定中间点的数量
 36 #pragma mark 摇晃动画
 37 // 课下练习动画的暂停和恢复
 38 + (CAKeyframeAnimation *)shakeAnimation
 39 {
 40     // 1. 实例化关键帧动画
 41     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
 42     
 43     // 晃动
 44 //    [anim setDuration:0.5f];
 45     
 46     // 1> 角度
 47     CGFloat angel = M_PI_4 / 12.0;
 48     [anim setValues:@[@(angel), @(-angel), @(angel)]];
 49     
 50     // 2> 循环晃
 51     [anim setRepeatCount:HUGE_VALF];
 52     
 53     // 3. 将动画添加到图层
 54     return anim;
 55 }
 56 
 57 #pragma mark 贝塞尔曲线,两个控制点
 58 + (CAKeyframeAnimation *)moveCurveWithDuration:(CFTimeInterval)duration from:(CGPoint)from to:(CGPoint)to
 59 {
 60     // 1. 实例化关键帧动画
 61     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
 62     
 63     // 2. 设置路径
 64     [anim setDuration:duration];
 65     
 66     // 中间的控制点使用屏幕上得随机点
 67     CGPoint cp1 = [AnimationView randomPoint];
 68     CGPoint cp2 = [AnimationView randomPoint];
 69     
 70     CGMutablePathRef path = CGPathCreateMutable();
 71     
 72     // 设置起始点
 73     CGPathMoveToPoint(path, NULL, from.x, from.y);
 74     // 添加带一个控制点的贝塞尔曲线
 75     CGPathAddCurveToPoint(path, NULL, cp1.x, cp1.y, cp2.x, cp2.y, to.x, to.y);
 76     
 77     [anim setPath:path];
 78     CGPathRelease(path);
 79     
 80 //    // 5) 设置键值记录目标位置,以便动画结束后,修正位置
 81 //    [anim setValue:@"translationTo" forKey:@"animationType"];
 82 //    [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
 83 //    [anim setDelegate:self];
 84     
 85     // 3. 将动画添加到图层
 86     return anim;
 87 }
 88 
 89 #pragma mark 贝塞尔曲线,一个控制点
 90 + (CAKeyframeAnimation *)moveQuadCurveWithDuration:(CFTimeInterval)duration from:(CGPoint)from to:(CGPoint)to
 91 {
 92     // 1. 实例化关键帧动画
 93     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
 94     
 95     // 2. 设置路径
 96     [anim setDuration:duration];
 97     
 98     // 中间的控制点使用屏幕上得随机点
 99     CGPoint cp = [self randomPoint];
100     
101     CGMutablePathRef path = CGPathCreateMutable();
102     
103     // 设置起始点
104     CGPathMoveToPoint(path, NULL, from.x, from.y);
105     // 添加带一个控制点的贝塞尔曲线
106     CGPathAddQuadCurveToPoint(path, NULL, cp.x, cp.y, to.x, to.y);
107     
108     [anim setPath:path];
109     CGPathRelease(path);
110     
111     // 5) 设置键值记录目标位置,以便动画结束后,修正位置
112     [anim setValue:@"translationTo" forKey:@"animationType"];
113     [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
114     [anim setDelegate:self];
115     
116     // 3. 将动画添加到图层
117     return anim;
118 }
119 
120 #pragma mark 按照矩形路径平移动画
121 // 移动的矩形是以当前点为矩形的一个顶点,目标点为矩形的对脚顶点
122 + (CAKeyframeAnimation *)moveRectWithDuration:(CFTimeInterval)duration from:(CGPoint)from to:(CGPoint)to
123 {
124     // 1. 实例化关键帧动画
125     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
126     
127     // 2. 按照矩形移动,需要使用到路径
128     [anim setDuration:duration];
129     
130     // 1) 创建路径
131     CGMutablePathRef path = CGPathCreateMutable();
132     // 2) 设置路径内容
133     // 起点,宽、高
134     CGFloat w = to.x - from.x;
135     CGFloat h = to.y - from.y;
136     CGRect rect = CGRectMake(from.x, from.y, w, h);
137     CGPathAddRect(path, nil, rect);
138     
139     // 3) 将路径添加到动画
140     [anim setPath:path];
141     
142     // 4) 释放路径
143     CGPathRelease(path);
144     
145     // 3. 将动画添加到图层
146     return anim;
147 }
148 
149 #pragma mark 使用随机中心点控制动画平移
150 + (CAKeyframeAnimation *)moveWithDuration:(CFTimeInterval)duration from:(CGPoint)from to:(CGPoint)to controlPointCount:(NSInteger)cpCount
151 {
152     // 1. 实例化关键帧动画
153     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
154     
155     // 2. 设置关键帧动画属性
156     [anim setDuration:duration];
157     
158     // 设置values
159     NSMutableArray *array = [NSMutableArray arrayWithCapacity:cpCount + 2];
160     
161     // 1) 将起始点添加到数组
162     [array addObject:[NSValue valueWithCGPoint:from]];
163     
164     // 2) 循环生成控制点位置数组
165     for (NSInteger i = 0; i < cpCount; i++) {
166         CGPoint p = [self randomPoint];
167         
168         [array addObject:[NSValue valueWithCGPoint:p]];
169     }
170     
171     // 3) 将目标点添加到数组
172     [array addObject:[NSValue valueWithCGPoint:to]];
173     
174     // 4) 设置values
175     [anim setValues:array];
176     
177     // 5) 设置键值记录目标位置,以便动画结束后,修正位置
178 //    [anim setValue:@"translationTo" forKey:@"animationType"];
179 //    [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
180 //    [anim setDelegate:self];
181     
182     // 3. 将动画添加到图层
183     return anim;
184 }
185 
186 #pragma mark - 基本动画
187 #pragma mark 缩放方法
188 + (CABasicAnimation *)scaleWithDuration:(CFTimeInterval)duration from:(CGFloat)from to:(CGFloat)to
189 {
190     // 1. 实例化基本动画
191     CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
192     
193     // 2. 设置动画属性
194     // fromValue & toValue
195     [anim setFromValue:@(from)];
196     // 从当前大小缩小到一半,然后恢复初始大小
197     [anim setToValue:@(to)];
198     // 自动翻转动画
199 //    [anim setAutoreverses:YES];
200     
201     // 动画时长
202     [anim setDuration:duration];
203     
204     return anim;
205 }
206 
207 + (CABasicAnimation *)opacityWithDuration:(CFTimeInterval)duration from:(CGFloat)from to:(CGFloat)to
208 {
209     // 1. 实例化基本动画
210     CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
211     
212     // 2. 设置动画属性
213     // fromValue & toValue
214     [anim setFromValue:@(from)];
215     // 从当前大小缩小到一半,然后恢复初始大小
216     [anim setToValue:@(to)];
217     // 自动翻转动画
218     //    [anim setAutoreverses:YES];
219     
220     // 动画时长
221     [anim setDuration:duration];
222     
223     return anim;
224 }
225 
226 + (CABasicAnimation *)rotationWithDuration:(CFTimeInterval)duration from:(CGFloat)from to:(CGFloat)to
227 {
228     // 1. 实例化基本动画
229     // 默认按照z轴旋转
230     CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
231 
232     // 2. 设置动画属性
233     // 不停的旋转
234     // 1) 旋转一周
235     [anim setToValue:@(to)];
236     
237     [anim setDuration:duration];
238     
239     return anim;
240 }

 

 
 

iOS开发——动画编程OC篇&(三)关键帧动画

标签:

原文地址:http://www.cnblogs.com/iCocos/p/4552963.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!