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

一、简单介绍

是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 }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值