通过改变图层 或者视图上面的属性值 产生动画
iOS 动画主要是指Core Animation框架。官方使用文档地址为: Core Animation Guide 。
Core Animation是iOS和OS X平台上负责图形渲染与动画的基础框架。Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作。你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用Core Animation的动画效果。Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且显示效果更加平滑,不会加重CPU的负担而影响程序的运行速度。
Core Animation类的继承关系图
+ (instancetype)animationWithKeyPath:(nullable NSString *)path
通过改变某个属性的值 到某个值(只能设置两个值来产生动画)
duration 动画的持续时间 默认为0 持续时间 受速度的影响 实际的动画完成时间 = 持续时间/速度
beginTime :动画开始的时间 默认为0
duration 动画的持续时间 默认为0 持续时间 受速度的影响 实际的动画完成时间 = 持续时间/速度
repeatCount : 动画的重复次数,默认是0(只播放一次)
timeOffset 动画播放时间的偏移量
repeatDuration 动画循环的持续时间 只能设置其中的一个属性 repeatCount/repeatDuration
autoreverses : 是否以动画的形式 返回之前的状态
.fillMode 设置当前对象在非活动时间段的状态
subtype : 过渡动画的动画方向
#import "ViewController.h" @interface ViewController () @property(nonatomic,strong) CALayer *layer; @property(nonatomic,strong) CALayer *petalLayer; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.layer.backgroundColor = [UIColor colorWithRed:0.913 green:0.614 blue:0.688 alpha:1.000].CGColor; [self.view.layer addSublayer:self.layer]; [self.view.layer addSublayer:self.petalLayer]; } //移动中心点(掉落) -(void)demo1:(CGPoint)toValue{ //利用KVO检测position属性 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; /* CGPoint —>转id CGPoint —> NSValue */ animation.fromValue = [NSValue valueWithCGPoint:self.petalLayer.position]; animation.toValue =[NSValue valueWithCGPoint:toValue]; animation.duration = 3;//设置动画的执行时间 animation.speed = 2;//动画速度,动画执行的总时间受动画速度的影响 //设置动画的timingFunction显示节奏 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; //设置动画在完成的时候固定在完成的状态,这个属性必须把removed设置为NO animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeBoth; //layer -> addAnimation :添加动画 [self.petalLayer addAnimation:animation forKey:@"可以通过key来找到这个动画"]; /* 查找某个key 对应的动画 CABasicAnimation *ad = (CABasicAnimation *)[self.petalLayer animationForKey:@"可以通过key来找到这个动画"]; */ } //心跳效果 -(void)demo2{ UIImage *image =[UIImage imageNamed:@"心跳.png"]; self.layer.contents = (id)image.CGImage; self.layer.bounds =CGRectMake(0, 0, image.size.width/10, image.size.height/10); self.layer.position = self.view.center; CABasicAnimation *animation =[CABasicAnimation animationWithKeyPath:@"bounds"]; /* 1、放大后 以动画的效果 还原到原来的位置 2、先慢后快 3、一直循环 */ animation.fromValue = [NSValue valueWithCGRect:self.layer.bounds]; animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, image.size.width/3, image.size.height/3)]; animation.repeatCount =HUGE; //设置动画的持续时间 animation.duration =0.5; //设置以动画的效果还原到原来的位置 animation.autoreverses =YES; animation.timingFunction =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [self.layer addAnimation:animation forKey:nil]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ [self demo1:[[touches anyObject] locationInView:self.view]]; [self demo2]; } -(CALayer *)layer{ if (_layer) { return _layer; } _layer =[CALayer layer]; _layer.position = CGPointMake(self.view.center.x, self.view.center.y+100); UIImage *image= [UIImage imageNamed:@"H4"]; _layer.bounds = CGRectMake(0, 0, image.size.width/3, image.size.height/3); _layer.contents = (id)image.CGImage;//设置layer上的内容 return _layer; } -(CALayer *)petalLayer{ if (_petalLayer) { return _petalLayer; } _petalLayer = [CALayer layer]; _petalLayer.position = CGPointMake(self.view.center.x, 50); UIImage *image= [UIImage imageNamed:@"H3"]; _petalLayer.bounds = CGRectMake(0, 0, image.size.width, image.size.height); _petalLayer.contents = (id)image.CGImage;//设置layer上的内容 return _petalLayer; }
_demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50); [UIView animateWithDuration:1.0f animations:^{ _demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50); } completion:^(BOOL finished) { _demoView.frame = CGRectMake(SCREEN_WIDTH/2-25, SCREEN_HEIGHT/2-50, 50, 50); }];
_demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50); [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:1.0f]; _demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50); [UIView commitAnimations];
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"position"]; anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-75)]; anima.toValue = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-75)]; anima.duration = 1.0f; [_demoView.layer addAnimation:anima forKey:@"positionAnimation"];
重要属性
fromValue: keyPath对应的初始值
toValue: keyPath对应的结束值
基础动画主要提供了对于CALayer对象中的可变属性进行简单动画的操作。比如:位移、透明度、缩放、旋转、背景色等等。
效果演示:
位移动画代码演示:
//使用CABasicAnimation创建基础动画 CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"position"]; anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-75)]; anima.toValue = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-75)]; anima.duration = 1.0f; //anima.fillMode = kCAFillModeForwards; //anima.removedOnCompletion = NO; [_demoView.layer addAnimation:anima forKey:@"positionAnimation"];
注意点
如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
CAKeyframeAnimation和CABaseAnimation都属于CAPropertyAnimatin的子类。CABaseAnimation只能从一个数值(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没有设置的时候,各个关键帧的时间是平分的。
效果演示:
圆形路径动画代码演示:
CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"position"]; UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 200, 200)]; anima.path = path.CGPath; anima.duration = 2.0f; [_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
说明:CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation
CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行。
重要属性
animations: 用来保存一组动画对象的NSArray
效果演示:
组动画代码演示:
CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"]; NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)]; NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)]; NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)]; NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)]; NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)]; NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)]; anima1.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil]; //缩放动画 CABasicAnimation *anima2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; anima2.fromValue = [NSNumber numberWithFloat:0.8f]; anima2.toValue = [NSNumber numberWithFloat:2.0f]; //旋转动画 CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; anima3.toValue = [NSNumber numberWithFloat:M_PI*4]; //组动画 CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; groupAnimation.animations = [NSArray arrayWithObjects:anima1,anima2,anima3, nil]; groupAnimation.duration = 4.0f; [_demoView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];
CAAnimation的子类,用于做过渡动画或者转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。
重要属性
type:动画过渡类型
Apple 官方的SDK其实只提供了四种过渡效果。
subtype:动画过渡方向
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)
效果演示:
###5.综合案例
效果演示:
动画解析:
1、点击红色按钮,红色按钮旋转。(旋转动画)
2、黑色小按钮依次弹出,并且带有旋转效果。(位移动画、旋转动画、组动画)
3、点击黑色小按钮,其他按钮消失,被点击的黑色按钮变大变淡消失。(缩放动画、alpha动画、组动画)
博主的话:代码过多,这里不做演示。文章最后提供代码下载地址。
效果演示:
看上去挺炫的,其实实现很简单,就是位移动画+缩放动画。
效果演示:
这里其实只有按钮变大效果使用的缩放动画。烟花效果 使用的是一种比较特殊的动画--粒子动画。
一个粒子系统一般有两部分组成:
1、CAEmitterCell:可以看作是单个粒子的原型(例如,一个单一的粉扑在一团烟雾)。当散发出一个粒子,UIKit根据这个发射粒子和定义的基础上创建一个随机粒子。此原型包括一些属性来控制粒子的图片,颜色,方向,运动,缩放比例和生命周期。
2、CAEmitterLayer:主要控制发射源的位置、尺寸、发射模式、发射源的形状等等。
以上两个类的属性还是比较多的,这里就不细讲了。大家可以google一下,详细的了解吧。
##总结任何复杂的动画其实都是由一个个简单的动画组装而成的,只要我们善于分解和组装,我们就能实现出满意的效果。动画其实也不是那么难。
感谢: