CoreAnimation笔记
核心动画继承结构
CoreAnimation
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Core Animation是直接作用在CALayer上的(并非UIView上)非常强大的跨Mac OS X和iOS平台的动画处理API,Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。 核心动画继承结构 核心动画继承结构 注意:核心动画中的虚类不能使用,而应该使用他们子类中的实类。 Core Animation的使用步骤 如果是Xcode6之前的版本,要导入<QuartzCore/QuartzCore.h>框架(并不存在什么CoreAnimation 框架) 开发步骤: 首先得有CALayer(因为CoreAnimation是作用在CALayer上的) 初始化一个CAAnimation对象,并设置一些动画相关属性 通过调用CALayer的addAnimation:forKey:方法,增加CAAnimation对象到CALayer中,这样就能开始执行动画了 通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画 CAAnimation中的一些属性: duration:动画的持续时间 repeatCount:重复次数,无限循环可以设置HUGE_VALF或者MAXFLOAT repeatDuration:重复时间 removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过*还要设置fillMode为kCAFillModeForwards* beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间 timingFunction:速度控制函数,控制动画运行的节奏 delegate:动画代理 fillMode决定当前对象在非active时间段的行为。(要想fillMode有效,最好设置removedOnCompletion = NO) kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态 kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态 kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。 kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态 CAMediaTimingFunction:速度控制函数 kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉 kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开 kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地 kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。 CAAnimation代理方法 CAAnimation在分类中定义了代理方法。是给NSObject添加的分类,所以任何对象,成为CAAnimation的代理,都可以。 动画开始的时候调用 - (void)animationDidStart:(CAAnimation *)anim; 动画停止的时候调用 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag; CALayer上动画的暂停和恢复 暂停 -(void)pauseLayer:(CALayer*)layer { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; // 让CALayer的时间停止走动 layer.speed = 0.0; // 让CALayer的时间停留在pausedTime这个时刻 layer.timeOffset = pausedTime; } 恢复 -(void)resumeLayer:(CALayer*)layer { CFTimeInterval pausedTime = layer.timeOffset; // 1. 让CALayer的时间继续行走 layer.speed = 1.0; // 2. 取消上次记录的停留时刻 layer.timeOffset = 0.0; // 3. 取消上次设置的时间 layer.beginTime = 0.0; // 4. 计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime) CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; // 5. 设置相对于父坐标系的开始时间(往后退timeSincePause) layer.beginTime = timeSincePause; } CABasicAnimation——基本动画 基本动画,是CAPropertyAnimation的子类 属性说明: keyPath :要改变的属性名称(传字符串) fromValue:keyPath相应属性的初始值 toValue:keyPath相应属性的结束值 动画过程说明: 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue keyPath内容是CALayer的可动画Animatable属性 如果fillMode=kCAFillModeForwards同时removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。 CAKeyframeAnimation——关键帧动画 关键帧动画,也是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 CAAnimationGroup——动画组 动画组,是CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行 属性说明: animations:用来保存一组动画对象的NSArray 默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间 转场动画——CATransition CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果 动画属性: type:动画过渡类型 subtype:动画过渡方向 startProgress:动画起点(在整体动画的百分比) endProgress:动画终点(在整体动画的百分比) 1. 单视图 + (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; 参数说明: duration:动画的持续时间 view:需要进行转场动画的视图 options:转场动画的类型 animations:将改变视图属性的代码放在这个block中 completion:动画结束后,会自动调用这个block 2. 双视图 + (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion; 参数说明: duration:动画的持续时间 options:转场动画的类型 animations:将改变视图属性的代码放在这个block中 completion:动画结束后,会自动调用这个block 3. 自己写转场 创建转场动画:[CATransition animation] 设置动画属性值 添加到需要转场动画的图层上 [layer addAnimation:animation forKey:nil] 转场动画的类型(NSString *type) fade : 交叉淡化过渡 push : 新视图把旧视图推出去 moveIn: 新视图移到旧视图上面 reveal: 将旧视图移开,显示下面的新视图 cube : 立方体翻滚效果 oglFlip : 上下左右翻转效果 suckEffect : 收缩效果,如一块布被抽走 rippleEffect: 水滴效果 pageCurl : 向上翻页效果 pageUnCurl : 向下翻页效果 cameraIrisHollowOpen : 相机镜头打开效果 cameraIrisHollowClos : 相机镜头关闭效果 转场动画的方向(NSString *subtype) 从某个方向开始:fromLeft, fromRight, fromTop ,fromBottom CoreAnimation中的CALayer 1. CAReplicatorLayer:复制图层 顾名思义,复制图层就是用来复制的。它会将自己的子图层进行复制,连同子layer上的动画会一起复制。 属性说明: instanceCount :复制份数。(会把原始的子图层复制多少份,包括原来的一份) instanceTransform:形变。每一份相对上一份的形变量 instanceDelay :每一份相对上一份的时间延迟。 修改CAReplicatorLayer的颜色通道,可以改变CAReplicatorLayer的显示的样式 @property float instanceRedOffset; @property float instanceGreenOffset; @property float instanceBlueOffset; @property float instanceAlphaOffset; 2. CAShapeLayer:形状图层 根据形状,绘制内容的图层 属性说明: path:描述形状的路径。默认会把路径封闭,然后填充。 fillColor :填充的颜色 strokeColor:描边的颜色(如果想仅仅只描边的话,就把fillColor设为clearcolor就好) strokeStart:开始描边的比例【0-1】 strokeEnd:结束描边的比例【0-1】 3. CAGradientLayer:渐变图层 用这个图层,可以做颜色的渐变 属性说明: colors :保存所有渐变的颜色,里面是CGColorRef,记得用id,让编译器以为数组里面的是OC对象。 locations :保存所有渐变的位置【0-1】 startPoint:开始渐变的点【0-1】 endPoint:结束渐变的点【0-1】 最后: 核心动画给我们展示的只是一个假象,layer的的frame、bounds、position并不会在动画完毕之后发生改变。 UIView封装的动画,会使会真实修改view的一些属性。
CABasicAnimation
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
CABasicAnimation 自己只有三个property fromValue toValue ByValue 当你创建一个 CABasicAnimation 时,你需要通过-setFromValue 和-setToValue 来指定一个开始值和结束值。 当你增加基础动画到层中的时候,它开始运行。当用属性做动画完成时,例如用位置属性做动画,层就会立刻 返回到它的初始位置 记住当你做动画时,你至少使用了 2 个对象。这些对象都是层本身,一个层或者层继承的对象,和在先前 的例子中你分配给层的 CABasicAnimation 对象。因为你给动画对象设定了最后的值(目的地),但是并不意 味着当动画完成的时候,层的属性就改变成了最后的值。当动画完成时,你必须显示的设定层的属性,这样动 画结束后,你的层才能真正的到你设定的属性值上。 你可以简单的停止动画到你结束的点上,但是这仅仅是一个视觉效果。层实际的值仍然是一样的。要真的 改变内部的值,就像刚才所说的你必须显示的设定那个属性。例如,显示的设定位置的属性,你需要在层中调 用-setPosition 方法。但是,这会造成一点问题。 如果你通过-set 这个方法显示的设定了层属性的值,那么默认的动画将被执行,而非之前你设定的动画。 在表 3-9 中演示了你设置位置的方法。注意到了,我们使用 position 已经创建了基础动画,但是我们在层上显 示的调用了-setPosition 方法,就覆盖了我们设定的动画,使我们设定的基础动画完全没用了。如果你使用了这 个代码,你会看到虽然我们的层结束的时候放到了正确的位置,但是它使用的是默认的 0.25 秒,而非我们在 动画里显示设定的 5 秒钟。 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@”position”]; [animation setFromValue:[NSValue valueWithPoint:startPoint]]; [animation setToValue:[NSValue valueWithPoint:endPoint]]; [animation setDuration:5.0]; [layer setPosition:endpoint]; [layer addAnimation:animation forKey:nil]; 因此现在问题出来了,你怎么能使用我们设定的动画呢?看表 3-9 的最后一行,注意到 forKey:这个参数 是被设定为 nil。这就是为什么动画不能覆盖默认动画的原因。如果你改变最后一行为[layer addAnimation:animation forKey:@"position"],动画将会按照我们设定的时间工作。这告诉了层当需要做动画时, 使用我们给关键路径指定的新动画。 下面是一些继承的游泳的属性 Autoreverses 当你设定这个属性为 YES 时,在它到达目的地之后,动画的返回到开始的值,代替了直接跳转到 开始的值。 Duration Duration 这个参数你已经相当熟悉了。它设定开始值到结束值花费的时间。期间会被速度的属性所影响。 RemovedOnCompletion 这个属性默认为 YES,那意味着,在指定的时间段完成后,动画就自动的从层上移除了。这个一般不用。 假如你想要再次用这个动画时,你需要设定这个属性为 NO。这样的话,下次你在通过-set 方法设定动画的属 性时,它将再次使用你的动画,而非默认的动画。 Speed 默认的值为 1.0.这意味着动画播放按照默认的速度。如果你改变这个值为 2.0,动画会用 2 倍的速度播放。 这样的影响就是使持续时间减半。如果你指定的持续时间为 6 秒,速度为 2.0,动画就会播放 3 秒钟---一半的 持续时间。 BeginTime 这个属性在组动画中很有用。它根据父动画组的持续时间,指定了开始播放动画的时间。默认的是 0.0.组 动画在下个段落中讨论“Animation Grouping”。 TimeOffset 如果一个时间偏移量是被设定,动画不会真正的可见,直到根据父动画组中的执行时间得到的时间都流逝 了。 RepeatCount 默认的是 0,意味着动画只会播放一次。如果指定一个无限大的重复次数,使用 1e100f。这个不应该和 repeatDration 属性一块使用。 RepeatDuration 这个属性指定了动画应该被重复多久。动画会一直重复,直到设定的时间流逝完。它不应该和 repeatCount 一起使用。 下面这段英文摘自苹果官方文档,将的是fromValue toValue ByValue 怎么使用 The interpolation values are used as follows: Both fromValue and toValue are non-nil. Interpolates between fromValue and toValue. fromValue and byValue are non-nil. Interpolates between fromValue and (fromValue + byValue). byValue and toValue are non-nil. Interpolates between (toValue - byValue) and toValue. fromValue is non-nil. Interpolates between fromValue and the current presentation value of the property. toValue is non-nil. Interpolates between the current value of keyPath in the target layer’s presentation layer andtoValue. byValue is non-nil. Interpolates between the current value of keyPath in the target layer’s presentation layer and that value plus byValue. All properties are nil. Interpolates between the previous value of keyPath in the target layer’s presentation layer and the current value of keyPath in the target layer’s presentation layer. 其他的方法 还是属性等 都是继承而来的 我们可以通过animationWithKeyPath键值对的方式来改变动画 animationWithKeyPath的值: transform.scale = 比例轉換 transform.scale.x = 闊的比例轉換 transform.scale.y = 高的比例轉換 transform.rotation.z = 平面圖的旋轉 opacity = 透明度 margin zPosition backgroundColor 背景颜色 cornerRadius 圆角 borderWidth bounds contents contentsRect cornerRadius frame hidden mask masksToBounds opacity position shadowColor shadowOffset shadowOpacity shadowRadius 下面是一些例子 CABasicAnimation *pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; pulse.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; pulse.duration = 0.5 + (rand() % 10) * 0.05; pulse.repeatCount = 1; pulse.autoreverses = YES; pulse.fromValue = [NSNumber numberWithFloat:.8]; pulse.toValue = [NSNumber numberWithFloat:1.2]; [self.ui_View.layer addAnimation:pulse forKey:nil]; // bounds CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"bounds"]; anim.duration = 1.f; anim.fromValue = [NSValue valueWithCGRect:CGRectMake(0,0,10,10)]; anim.toValue = [NSValue valueWithCGRect:CGRectMake(10,10,200,200)]; anim.byValue = [NSValue valueWithCGRect:self. ui_View.bounds]; // anim.toValue = (id)[UIColor redColor].CGColor; // anim.fromValue = (id)[UIColor blackColor].CGColor; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; anim.repeatCount = 1; anim.autoreverses = YES; [ui_View.layer addAnimation:anim forKey:nil]; //cornerRadius CABasicAnimation *anim2 = [CABasicAnimation animationWithKeyPath:@"cornerRadius"]; anim2.duration = 1.f; anim2.fromValue = [NSNumber numberWithFloat:0.f]; anim2.toValue = [NSNumber numberWithFloat:20.f]; anim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; anim2.repeatCount = CGFLOAT_MAX; anim2.autoreverses = YES; [ui_View.layer addAnimation:anim2 forKey:@"cornerRadius"]; //contents CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"contents"]; anim.duration = 1.f; anim.fromValue = (id)[UIImage imageNamed:@"1.jpg"].CGImage; anim.toValue = (id)[UIImage imageNamed:@"2.png"].CGImage; // anim.byValue = (id)[UIImage imageNamed:@"3.png"].CGImage; // anim.toValue = (id)[UIColor redColor].CGColor; // anim.fromValue = (id)[UIColor blackColor].CGColor; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; anim.repeatCount = CGFLOAT_MAX; anim.autoreverses = YES; [ui_View.layer addAnimation:anim forKey:nil]; [ui_View.layer setShadowOffset:CGSizeMake(2,2)]; [ui_View.layer setShadowOpacity:1]; [ui_View.layer setShadowColor:[UIColor grayColor].CGColor]; // CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"shadowColor"]; anim.duration = 1.f; anim.toValue = (id)[UIColor redColor].CGColor; anim.fromValue = (id)[UIColor blackColor].CGColor; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; anim.repeatCount = CGFLOAT_MAX; anim.autoreverses = YES; [ui_View.layer addAnimation:anim forKey:nil]; CABasicAnimation *_anim = [CABasicAnimation animationWithKeyPath:@"shadowOffset"]; _anim.duration = 1.f; _anim.fromValue = [NSValue valueWithCGSize:CGSizeMake(0,0)]; _anim.toValue = [NSValue valueWithCGSize:CGSizeMake(3,3)]; _anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; _anim.repeatCount = CGFLOAT_MAX; _anim.autoreverses = YES; [ui_View.layer addAnimation:_anim forKey:nil]; CABasicAnimation *_anim1 = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"]; _anim1.duration = 1.f; _anim1.fromValue = [NSNumber numberWithFloat:0.5]; _anim1.toValue = [NSNumber numberWithFloat:1]; _anim1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; _anim1.repeatCount = CGFLOAT_MAX; _anim1.autoreverses = YES; [ui_View.layer addAnimation:_anim1 forKey:nil]; CABasicAnimation *_anim2 = [CABasicAnimation animationWithKeyPath:@"shadowRadius"]; _anim2.duration = 1.f; _anim2.fromValue = [NSNumber numberWithFloat:10]; _anim2.toValue = [NSNumber numberWithFloat:5]; _anim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; _anim2.repeatCount = CGFLOAT_MAX; _anim2.autoreverses = YES; [ui_View.layer addAnimation:_anim2 forKey:nil]; 下面是一些应用 几个可以用来实现热门APP应用PATH中menu效果的几个方法 +(CABasicAnimation *)opacityForever_Animation:(float)time //永久闪烁的动画 { CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue=[NSNumber numberWithFloat:1.0]; animation.toValue=[NSNumber numberWithFloat:0.0]; animation.autoreverses=YES; animation.duration=time; animation.repeatCount=FLT_MAX; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; return animation; } +(CABasicAnimation *)opacityTimes_Animation:(float)repeatTimes durTimes:(float)time; //有闪烁次数的动画 { CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue=[NSNumber numberWithFloat:1.0]; animation.toValue=[NSNumber numberWithFloat:0.4]; animation.repeatCount=repeatTimes; animation.duration=time; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; animation.autoreverses=YES; return animation; } +(CABasicAnimation *)moveX:(float)time X:(NSNumber *)x //横向移动 { CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.translation.x"]; animation.toValue=x; animation.duration=time; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; return animation; } +(CABasicAnimation *)moveY:(float)time Y:(NSNumber *)y //纵向移动 { CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.translation.y"]; animation.toValue=y; animation.duration=time; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; return animation; } +(CABasicAnimation *)scale:(NSNumber *)Multiple orgin:(NSNumber *)orginMultiple durTimes:(float)time Rep:(float)repeatTimes //缩放 { CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.scale"]; animation.fromValue=orginMultiple; animation.toValue=Multiple; animation.duration=time; animation.autoreverses=YES; animation.repeatCount=repeatTimes; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; return animation; } +(CAAnimationGroup *)groupAnimation:(NSArray *)animationAry durTimes:(float)time Rep:(float)repeatTimes //组合动画 { CAAnimationGroup *animation=[CAAnimationGroup animation]; animation.animations=animationAry; animation.duration=time; animation.repeatCount=repeatTimes; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; return animation; } +(CAKeyframeAnimation *)keyframeAniamtion:(CGMutablePathRef)path durTimes:(float)time Rep:(float)repeatTimes //路径动画 { CAKeyframeAnimation *animation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; animation.path=path; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; animation.autoreverses=NO; animation.duration=time; animation.repeatCount=repeatTimes; return animation; } +(CABasicAnimation *)movepoint:(CGPoint )point //点移动 { CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.translation"]; animation.toValue=[NSValue valueWithCGPoint:point]; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; return animation; } +(CABasicAnimation *)rotation:(float)dur degree:(float)degree direction:(int)direction repeatCount:(int)repeatCount //旋转 { CATransform3D rotationTransform = CATransform3DMakeRotation(degree, 0, 0,direction); CABasicAnimation* animation; animation = [CABasicAnimation animationWithKeyPath:@"transform"]; animation.toValue= [NSValue valueWithCATransform3D:rotationTransform]; animation.duration= dur; animation.autoreverses= NO; animation.cumulative= YES; animation.removedOnCompletion=NO; animation.fillMode=kCAFillModeForwards; animation.repeatCount= repeatCount; animation.delegate= self; return animation; }
CAKeyframeAnimation
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
之所以叫做关键帧动画是因为,这个类可以实现,某一属性按照一串的数值进行动画,就好像制作动画的时候一帧一帧的制作一样。 一般使用的时候 首先通过 animationWithKeyPath 方法 创建一个CAKeyframeAnimation实例, CAKeyframeAnimation 的一些比较重要的属性 1. path 这是一个 CGPathRef 对象,默认是空的,当我们创建好CAKeyframeAnimation的实例的时候,可以通过制定一个自己定义的path来让 某一个物体按照这个路径进行动画。这个值默认是nil 当其被设定的时候 values 这个属性就被覆盖 2. values 一个数组,提供了一组关键帧的值, 当使用path的 时候 values的值自动被忽略。 下面是一个简单的例子 效果为动画的连续移动一个block到不同的位置 CGMutablePathRef path = CGPathCreateMutable(); //将路径的起点定位到 (50 120) CGPathMoveToPoint(path,NULL,50.0,120.0); //下面5行添加5条直线的路径到path中 CGPathAddLineToPoint(path, NULL, 60, 130); CGPathAddLineToPoint(path, NULL, 70, 140); CGPathAddLineToPoint(path, NULL, 80, 150); CGPathAddLineToPoint(path, NULL, 90, 160); CGPathAddLineToPoint(path, NULL, 100, 170); //下面四行添加四条曲线路径到path CGPathAddCurveToPoint(path,NULL,50.0,275.0,150.0,275.0,70.0,120.0); CGPathAddCurveToPoint(path,NULL,150.0,275.0,250.0,275.0,90.0,120.0); CGPathAddCurveToPoint(path,NULL,250.0,275.0,350.0,275.0,110.0,120.0); CGPathAddCurveToPoint(path,NULL,350.0,275.0,450.0,275.0,130.0,120.0); //以“position”为关键字 创建 实例 CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; //设置path属性 [animation setPath:path]; [animation setDuration:3.0]; //这句代码 表示 是否动画回到原位 // [animation setAutoreverses:YES]; CFRelease(path); [self.block.layer addAnimation:animation forKey:NULL]; 运行后 block会先沿着直线移动,之后再沿着设定的曲线移动,完全按照我们设定的“关键帧”移动。 下面一个例子是利用values制作的动画 CGPoint p1=CGPointMake(50, 120); CGPoint p2=CGPointMake(80, 170); CGPoint p3=CGPointMake(30, 100); CGPoint p4=CGPointMake(100, 190); CGPoint p5=CGPointMake(200, 10); NSArray *values=[NSArray arrayWithObjects:[NSValue valueWithCGPoint:p1],[NSValue valueWithCGPoint:p2],[NSValue valueWithCGPoint:p3],[NSValue valueWithCGPoint:p4],[NSValue valueWithCGPoint:p5], nil]; CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; [animation setValues:values]; [animation setDuration:3.0]; [animation setAutoreverses:YES]; [self.block.layer addAnimation:animation forKey:NULL]; 也非常简单,到目前位置,只用到了CAKeyframeAnimation的两个关键属性就能完成动画,下面的一些属性提供了更加细致化,更加强大的功能。 设定每一帧的时间 默认情况下,一帧动画的播放,分割 的时间是动画的总时间除以帧数减去一。你可以通过下面的公式决定每帧动画的时间:总时间/(总帧数-1)。 例如,如果你指定了一个 5 帧,10 秒的动画,那么每帧的时间就是 2.5 秒钟:10/(5-1)=2.5。你可以做更多 的控制通过使用 keyTimes 关键字,你可以给每帧动画指定总时间之内的某个时间点。 通过设置属性keyTimes,能实现这个功能,这个属性是一个数组,其成员必须是NSNumber。 同时 这个属性的设定值要与calculationMode属性相结合,同时他们有一定的规则, The appropriate values in the keyTimes array are dependent on the calculationMode property. If the calculationMode is set to kCAAnimationLinear, the first value in the array must be 0.0 and the last value must be 1.0. Values are interpolated between the specified key times. If the calculationMode is set to kCAAnimationDiscrete, the first value in the array must be 0.0. If the calculationMode is set to kCAAnimationPaced or kCAAnimationCubicPaced, the keyTimes array is ignored。 如果keyTimes的值不合法,或者不符合上面的规则,那么就会被忽略。 1 2 3 4 5 [animation setCalculationMode:kCAAnimationLinear]; [animation setKeyTimes: [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.25], [NSNumber numberWithFloat:0.50], [NSNumber numberWithFloat:0.75], [NSNumber numberWithFloat:1.0], nil]]; calculationMode 这个属性用来设定 关键帧中间的值是怎么被计算的 可选的值有 NSString * const kCAAnimationLinear; NSString * const kCAAnimationDiscrete; 只展示关键帧的状态,没有中间过程,没有动画。 NSString * const kCAAnimationPaced; NSString * const kCAAnimationCubic; NSString * const kCAAnimationCubicPaced; 关键帧动画的基础步骤 1.决定你想要做动画的属性(例如,框架,背景,锚点,位置,边框,等等) 2.在动画对象值的区域中,指定开始,结束,和中间的值。这些都是你的关键帧(看清单 4-2) 3.使用 duration 这个字段指定动画的时间 4.通常来讲,通过使用 times 这个字段,来给每帧动画指定一个时间。如果你没有指定这些,核心动画就 会通过你在 values 这个字段指定的值分割出时间段。 5.通常,指定时间功能来控制步调。 这些都是你需要做的。你创建你的动画和增加他们到层中。调用-addAnimation 就开始了动画
CATransition
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
转场动画就是从一个场景以动画的形式过渡到另一个场景。转场动画的使用一般分为以下几个步骤: 1.创建转场动 2.设置转场类型、子类型(可选)及其他属性画 3.设置转场后的新视图并添加动画到图层 下表列出了常用的转场类型(注意私有API是苹果官方没有公开的动画类型,但是目前通过仍然可以使用): 动画类型 说明 对应常量 是否支持方向设置 公开API fade 淡出效果 kCATransitionFade 是 movein 新视图移动到旧视图上 kCATransitionMoveIn 是 push 新视图推出旧视图 kCATransitionPush 是 reveal 移开旧视图显示新视图 kCATransitionReveal 是 私有API 私有API只能通过字符串访问 cube 立方体翻转效果 无 是 oglFlip 翻转效果 无 是 suckEffect 收缩效果 无 否 rippleEffect 水滴波纹效果 无 否 pageCurl 向上翻页效果 无 是 pageUnCurl 向下翻页效果 无 是 cameralIrisHollowOpen 摄像头打开效果 无 否 cameraIrisHollowClose 摄像头关闭效果 无 否 另外对于支持方向设置的动画类型还包含子类型: 动画子类型 说明 kCATransitionFromRight 从右侧转场 kCATransitionFromLeft 从左侧转场 kCATransitionFromTop 从顶部转场 kCATransitionFromBottom 从底部转场 //添加手势 UISwipeGestureRecognizer *leftSwipeGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)]; leftSwipeGesture.direction=UISwipeGestureRecognizerDirectionLeft; [self.view addGestureRecognizer:leftSwipeGesture]; UISwipeGestureRecognizer *rightSwipeGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)]; rightSwipeGesture.direction=UISwipeGestureRecognizerDirectionRight; [self.view addGestureRecognizer:rightSwipeGesture]; UISwipeGestureRecognizer *topSwipeGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(topSwipe:)]; topSwipeGesture.direction=UISwipeGestureRecognizerDirectionUp; [self.view addGestureRecognizer:topSwipeGesture]; UISwipeGestureRecognizer *bottomSwipeGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(bottomSwipe:)]; bottomSwipeGesture.direction=UISwipeGestureRecognizerDirectionDown; [self.view addGestureRecognizer:bottomSwipeGesture]; #pragma mark 向左滑动浏览下一张图片 -(void)leftSwipe:(UISwipeGestureRecognizer *)gesture{ [self transitionAnimation:1]; } #pragma mark 向右滑动浏览上一张图片 -(void)rightSwipe:(UISwipeGestureRecognizer *)gesture{ [self transitionAnimation:2]; } -(void)topSwipe:(UISwipeGestureRecognizer *)gesture{ [self transitionAnimation:3]; } -(void)bottomSwipe:(UISwipeGestureRecognizer *)gesture{ [self transitionAnimation:4]; } #pragma mark 转场动画 -(void)transitionAnimation:(NSInteger)direction{ //1.创建转场动画对象 CATransition *transition=[[CATransition alloc]init]; //2.设置动画类型,注意对于苹果官方没公开的动画类型只能使用字符串,并没有对应的常量定义 transition.type=@"rippleEffect"; BOOL bl = YES; //设置子类型 if (direction == 1) { transition.subtype=kCATransitionFromRight; bl = YES; }else if (direction == 2) { transition.subtype=kCATransitionFromLeft; bl = NO; }else if (direction == 3) { transition.subtype=kCATransitionFromTop; bl = YES; }else{ transition.subtype=kCATransitionFromBottom; bl = NO; } //设置动画时常 transition.duration=1.0f; //3.设置转场后的新视图添加转场动画 if (bl) { currentIndex=(currentIndex+1)%IMAGE_COUNT; }else{ currentIndex=(currentIndex-1+IMAGE_COUNT)%IMAGE_COUNT; } NSString *imageName=[NSString stringWithFormat:@"%d",(int)currentIndex]; _imageView.image = [UIImage imageNamed:imageName]; [_imageView.layer addAnimation:transition forKey:@"KCTransitionAnimation1"]; } 或者用UIView动画来实现转场: #pragma mark 转场动画 -(void)transitionAnimation:(BOOL)isNext{ UIViewAnimationOptions option; if (isNext) { option=UIViewAnimationOptionCurveLinear|UIViewAnimationOptionTransitionFlipFromRight; }else{ option=UIViewAnimationOptionCurveLinear|UIViewAnimationOptionTransitionFlipFromLeft; } [UIView transitionWithView:_imageView duration:1.0 options:option animations:^{ _imageView.image=[self getImage:isNext]; } completion:nil]; }
Q&A:
Q:CABasicAnimation 如何解决保持移动后的位置状态不变
A:
CABasicAnimation 如何解决保持移动后的位置状态不变
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; [rotationAnimation setRepeatCount:0]; [rotationAnimation setDuration:0.6]; [rotationAnimation setAutoreverses:NO]; //以下两行同时设置才能保持移动后的位置状态不变,但这只是界面显示不变的假象,还需要设置代理,在动画结束时,设置最终layer的位置 rotationAnimation.fillMode=kCAFillModeForwards; rotationAnimation.removedOnCompletion = NO; rotationAnimation.delegate = self; [rotationAnimation setFromValue:[NSNumber numberWithFloat:0.0]]; [rotationAnimation setToValue:[NSNumber numberWithFloat:(float) (M_PI/value)*derection]]; [self.layer addAnimation:rotationAnimation forKey:kBTSWiggleTransformAnimation]; 代理: - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ [self.layer setTransform:_myTransform]; }
A:还有一种比较偏的方法,设置performSelector:withObject:afterDelay:,把delay的时间设置和动画的时间一样就行,笔者没试过
链接:
UIViewAnimation动画与Core Animation的CATransition类动画
IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
IOS 3D UI --- CALayer的transform扩展
CAEmitterLayer(粒子系统)学习笔记(含Demo)
iOS开发之iOS中的动画实现,通过CAShapeLayer、CAShapeLayer,CAReplicatorLayer实现炫酷的动画、雷达效果,波纹效果,咻一咻效果。iOS核心动画实现。
#MARK--UIDynamic