iOS_核心动画(二)
目 录:
一、Core Animation开发步骤
二、Core Animation的继承结构
三、CAAnimation常用的属性
四、CAPropertyAnimation(属性动画)
五、CABasicAnimation(基本动画)
六、CAKeyframeAnimation(关键帧动画)
七、CAAnimationGroup(动画组)
八、CATransition(转场动画)
上节中分享了核心动画的基础部分CALayer,知道了核心动画的操作对象不是UIView,而是基于CALayer。今天来看下Core Animation如何实现动画效果的。
注意:图中的黑色虚线代表“继承”某个类,红色虚线代表“遵守”某个协议。
从上图可以看出CAAnimation时所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,如果设置动画应该使用它具体的子类。
(1)CAAnimation:它是所有动画类的基类,它实现了CAMediaTiming协议,提供了动画的持续时间、速度和重复计数等。CAAnimation还实现了CAAction协议,该协议为CALayer动画触发的动作提供标准化响应。
(2)CATransition:可以通过预置的过渡效果来控制CALayer层的过渡动画。
(3)CAPropertyAnimation:它代表一个属性动画,可通过+animationWithKeyPath:类方法来创建属性动画实例(程序一般创建该子类的实例),该方法需要指定一个CALayer支持动画的属性,然后通过它的子类控制CALayer的动画属性慢慢睇改变,即可实现CALayer动画。
(4)CBasicAnimation:简单地控制CALayer层的属性慢慢改变,从而实现动画效果。很多CALayer层的属性值的修改默认会执行这个动画类。比如大小、透明度、颜色等属性。
(5)CAKeyframeAnimation:支持关键帧的属性动画,该动画的最大特点在于可通过values属性指定多个关键帧,通过多个关键帧可以指定动画的各阶段的关键值。
(6)CAAnimationGroup:用于将多个动画组合在一起执行。
三、CAAnimation常用的属性(红色代表来自CAMediaTiming协议的属性)。
(1) duration:动画的持续时间
(2) repeatCount:重复的次数,无线循环可以设置HUGE_VALF或者MAXFLOAT
(3)repeatDuration:重复时间
(4)removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards(产生一个动画将CALayer移动到另外一个位置,而CALayer的实际位置却没有改变,仍然在动画开启前的位置)
默认值为0,无延迟
#import "ViewController.h" @interface ViewController ()
@property(strong,nonatomic)CALayer *subLayer; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
//创建子层
self.subLayer = [CALayer layer];
self.subLayer.bounds = CGRectMake(, , , );
self.subLayer.position = CGPointMake(, );
self.subLayer.cornerRadius = ;
self.subLayer.backgroundColor = [[UIColor greenColor]CGColor]; [self.view.layer addSublayer:self.subLayer]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)]; tap.numberOfTapsRequired = ;
//接受几个手指响应的事件
tap.numberOfTouchesRequired = ;
[self.view addGestureRecognizer:tap]; }
-(void)tap:(UITapGestureRecognizer *)sender
{
CGPoint location = [sender locationInView:self.view];
CABasicAnimation *basic = [[CABasicAnimation alloc]init];
basic.duration = 3.0;//动画时长
basic.keyPath = @"position";
basic.removedOnCompletion = NO;
basic.fillMode = kCAFillModeForwards;
basic.delegate = self;
//将动画的结束位置移动到点击的坐标处
basic.toValue = [NSValue valueWithCGPoint:location];
[self.subLayer addAnimation:basic forKey:@"basic"]; }
- (IBAction)pauseClicked:(UIButton *)sender
{
if (sender.tag == )
{
//动画暂停
[self animationPause];
sender.tag = ;
}
else
{
//动画恢复
[self animationResume];
sender.tag = ;
}
}
//动画暂停
-(void)animationPause
{
//获取当前暂停的时间段
CFTimeInterval pauseTime = [self.subLayer convertTime:CACurrentMediaTime() fromLayer:nil];
NSLog(@"pausetTime:%f",pauseTime); //将速度降为0,动画停止
self.subLayer.speed = 0.0;
//保存暂停时间
self.subLayer.timeOffset = pauseTime;
}
-(void)animationResume
{
CFTimeInterval pauseTime = self.subLayer.timeOffset;
self.subLayer.timeOffset = pauseTime;
self.subLayer.speed = 1.0;
self.subLayer.beginTime = 0.0; //计算开始时间
CFTimeInterval beginTime = [self.subLayer convertTime:CACurrentMediaTime() fromLayer:nil]-pauseTime;
self.subLayer.beginTime = beginTime;
// NSLog(@"beginTime:%@",beginTime); }
#pragma mark - 动画代理的方法
//动画开始
-(void)animationDidStart:(CAAnimation *)anim
{
NSLog(@"animationDidStart");
}
//动画结束
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//
NSLog(@"%@",((CABasicAnimation *)anim).toValue);
NSValue *toValue = ((CABasicAnimation *)anim).toValue;
CGPoint location = [toValue CGPointValue];
self.subLayer.position = location;
} @end
六、CAKeyframeAnimation(关键帧动画)
关键帧动画也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
属性说明:
- values:上述的NSArray对象。里面的元素称为“帧”。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧。
- path:可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和positon起作用。如果设置了path,那么values将被忽略
- keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的。
#import "ViewController.h"
#define MAX_TOUCH_NUM 5//最大点击次数
@interface ViewController ()
@property(strong,nonatomic)NSMutableArray *points;
@property(strong,nonatomic)CALayer *subLayer;
@property(assign,nonatomic)CGMutablePathRef path;
@property(strong,nonatomic)CALayer *drawLayer; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
//添加绘图层
self.drawLayer = [CALayer layer];
self.drawLayer.bounds = self.view.bounds;
self.drawLayer.position = self.view.center;
self.drawLayer.backgroundColor = [[UIColor whiteColor]CGColor];
[self.view.layer addSublayer:self.drawLayer]; //创建子层
self.subLayer = [CALayer layer];
self.subLayer.bounds = CGRectMake(, , , );
self.subLayer.position = CGPointMake(, );
self.subLayer.backgroundColor = [[UIColor greenColor]CGColor]; [self.view.layer addSublayer:self.subLayer]; self.points = [NSMutableArray array];
// //设置跟layer的代理
self.drawLayer.delegate = self; }
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view]; //创建路径
self.path = CGPathCreateMutable();
CGPathMoveToPoint(self.path, nil, location.x, location.y); }
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//将当前点加到路径中去
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
CGPathAddLineToPoint(self.path,nil, location.x, location.y);
[self.drawLayer setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//创建帧动画(路径动画)
CAKeyframeAnimation *keyFrame = [[CAKeyframeAnimation alloc]init];
keyFrame.keyPath = @"position";
keyFrame.path = self.path;
keyFrame.duration = 3.0f;
//设置动画保存在最后的位置
keyFrame.removedOnCompletion = NO;
keyFrame.fillMode = kCAFillModeForwards; keyFrame.delegate = self;
[self.subLayer addAnimation:keyFrame forKey:@"keyFrame"]; }
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
CGPathRelease(self.path);
}
#pragma mark - 层绘制的代理方法
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
CGContextAddPath(ctx, self.path);
CGContextSetStrokeColorWithColor(ctx, [[UIColor blueColor]CGColor]);
CGContextDrawPath(ctx, kCGPathStroke); }
@end
运行效果图,如下:
七、CAAnimationGroup动画组
动画组是CAAnimation子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中的所有动画可以同时并发运行。
属性说明:
- animations:用来管理多个动画对象的NSArray。默认情况下,多个动画是同时执行的,可以通过设置动画对象的beginTime来改变动画的开始执行时间。
案例分析:
#import "ViewController.h" @interface ViewController ()
@property(strong,nonatomic)CALayer *subLayer; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
//创建子层
self.subLayer = [CALayer layer];
self.subLayer.bounds = CGRectMake(, , , );
self.subLayer.position = CGPointMake(, );
self.subLayer.backgroundColor = [[UIColor blueColor]CGColor]; [self.view.layer addSublayer:self.subLayer]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
tap.numberOfTapsRequired = ;
tap.numberOfTouchesRequired = ;
[self.view addGestureRecognizer:tap];
}
//创建旋转动画
-(CABasicAnimation *)rotationAnimationFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue
{
//创建基本动画
CABasicAnimation *animationRotation = [[CABasicAnimation alloc]init];
animationRotation.keyPath = @"transform.rotation.z";
animationRotation.fromValue = @(fromValue);
animationRotation.toValue = @(toValue);
animationRotation.duration = 1.0f; animationRotation.removedOnCompletion = NO;
animationRotation.fillMode = kCAFillModeForwards;
return animationRotation; }
//创建缩放动画
-(CABasicAnimation *)scaleAnimationFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue
{
CABasicAnimation *scaleAnimation = [[CABasicAnimation alloc]init];
scaleAnimation.keyPath = @"transform.scale";
scaleAnimation.fromValue = @(fromValue);
scaleAnimation.toValue = @(toValue);
scaleAnimation.duration = 2.0f;
scaleAnimation.removedOnCompletion = NO;
scaleAnimation.fillMode = kCAFillModeForwards;
return scaleAnimation; }
-(void)tap:(UITapGestureRecognizer *)sender
{
//创建动画组
CAAnimationGroup *group = [[CAAnimationGroup alloc]init];
NSArray *animations = @[[self rotationAnimationFromValue:-M_PI toValue:-M_PI_4], [self scaleAnimationFromValue:1.0 toValue:2.0]];
group.animations = animations;
//动画组中的动画的属性,受动画组的控制(比如:动画内设置了大小,时长,在动画组内不起作用,以动画组设置为准)
group.duration = 4.0f;
// group.removedOnCompletion = NO;
// group.fillMode = kCAFillModeForwards;
//延时执行
// group.beginTime = CACurrentMediaTime()+1.0f;
[self.subLayer addAnimation:group forKey:@"animation"]; }
@end
八、CATransition转场动画
CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS 比Mac OSX的转场动画效果少一点。
#import "ViewController.h" @interface ViewController ()
@property(strong,nonatomic)UIImageView *imageView;
@property(assign,nonatomic)NSInteger index; @end @implementation ViewController - (void)viewDidLoad
{
[super viewDidLoad];
self.index = ; //创建imageView;
self.imageView = [[UIImageView alloc]initWithFrame:self.view.frame];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg",self.index]];
self.imageView.userInteractionEnabled = YES;
[self.view addSubview:self.imageView]; UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
[self.imageView addGestureRecognizer:leftSwipe]; UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
[self.imageView addGestureRecognizer:rightSwipe];
}
-(void)leftSwipe:(UISwipeGestureRecognizer *)sender
{
if (sender.direction == UISwipeGestureRecognizerDirectionLeft)
{
if (self.index > )
{
self.index--;
}
}
else
{
if (self.index < )
{
self.index++;
}
}
//过场动画
CATransition *transition = [[CATransition alloc]init];
//动画类型
transition.type = @"cube";
//设置方向
transition.subtype = kCATransitionFromBottom;
//设置时长
transition.duration = 0.5f;
//添加动画
[self.imageView.layer addAnimation:transition forKey:@"transition"]; self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg",self.index]];
} @end
到此,核心动画就完结了。
iOS_核心动画(二)的更多相关文章
- iOS_核心动画CALayer(一)
目 录: 一.核心动画简介 二.图层与视图之间的关系 三.CALayer的使用说明 四.CALayer的隐式动画属性 五.在CALayer上绘图 六.总结 一.核心动画简介 Core Anim ...
- ios开发图层layer与核心动画二:CATransform3D,CAlayear和UIView区别,layer的position和anchorpoint
一:CATransform3D #import "ViewController.h" @interface ViewController () @property (weak, n ...
- CoreAnimation 核心动画二 锚点
锚点: anchorPoint 以锚点为中心 执行动画 (与 渔夫固定船的点时一致的) anchorPoint 默认是 0.5,0.5 (注意: 锚点 是一个比例) anchorPoint ...
- iOS核心动画高级技巧之图层变换和专用图层(二)
iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...
- iOS开发UI篇—核心动画(UIView封装动画)
iOS开发UI篇—核心动画(UIView封装动画) 一.UIView动画(首尾) 1.简单说明 UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画 ...
- iOS开发UI篇—核心动画(转场动画和组动画)
转自:http://www.cnblogs.com/wendingding/p/3801454.html iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的 ...
- iOS开发UI篇—核心动画(关键帧动画)
转自:http://www.cnblogs.com/wendingding/p/3801330.html iOS开发UI篇—核心动画(关键帧动画) 一.简单介绍 是CApropertyAnimatio ...
- iOS开发UI篇—核心动画(基础动画)
转自:http://www.cnblogs.com/wendingding/p/3801157.html 文顶顶 最怕你一生碌碌无为 还安慰自己平凡可贵 iOS开发UI篇—核心动画(基础动画) iOS ...
- iOS开发UI篇—核心动画简介
转自:http://www.cnblogs.com/wendingding/p/3801036.html iOS开发UI篇—核心动画简介 一.简单介绍 Core Animation,中文翻译为核心动画 ...
随机推荐
- WPF数据模板样式选择器
在使用数据模板样式选择器时,不能设置ItemContainerStyle的属性值,如果设置了该值,那么数据模板样式选择器会失去作用. 在使用数据模板样式选择器时,首先要创建数据模板样式选择器对象,此对 ...
- Asp.Net 无刷新文件上传并显示进度条的实现方法及思路
相信通过Asp.Net的服务器控件上传文件在简单不过了,通过AjaxToolkit控件实现上传进度也不是什么难事,为什么还要自己辛辛苦苦来 实现呢?我并不否认”拿来主义“,只是我个人更喜欢凡是求个所以 ...
- nginx配置后只有根目录首页index.php能访问,其他页面404
只有首页面根目录可以访问,其他页面地址都是404 not found.网上找了半天url重定向,url重写都试了无效,要不就是重定向过多,下图为跳坑历程. location / { #if ($htt ...
- tomcat NIO配置
1.tomcat NIO配置 今天在查看日志时发现tomcat的Socket连接方式为bio,于是我想既然有bio那肯定有nio.果然,一查就发现tomcat在6.0之后就可以配置nio的方式.nio ...
- keycode 大全,javascript 再也不用操心我不知道的keycode了
keycode 8 = BackSpace BackSpace keycode 9 = Tab Tab keycode 12 = Clear keycode 13 = Enter ...
- Eclipse 启动时闪退问题解决方案
一.以前Eclipse都可以正常使用,突然有一天不能启动了,点击图标后启动画面一闪之后就消失了,以下是一些解决方案: 1. 找到Eclipse目录下的eclipse.exe,右键点击->发送到桌 ...
- 【BZOJ3073】[Pa2011]Journeys 线段树+堆优化Dijkstra
[BZOJ3073][Pa2011]Journeys Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在 ...
- 《从零开始学Swift》学习笔记(Day 47)——final关键字
原创文章,欢迎转载.转载请注明:关东升的博客 在类的定义中使用final关键字声明类.属性.方法和下标.final声明的类不能被继承,final声明的属性.方法和下标不能被重写. 下面看一个示例: f ...
- Linux安装mysql8.*
分别在Linux和windows上安装mysql8.* 环境 CentOS7 安装mysql8 步骤: window下的Navicat 连接MySql8: 第一部分 CentOS7安装mysql8 1 ...
- idea 不能编译生成class文件
问题:开发工程中将idea中编译输出目录 out 删掉.发现再次编译不能生成class文件 解决方案:settings -> compiler 勾选自动编译选项