目录:
- UIView动画
- Core Animation
- 自定义转场动画
- UIDynamicAnimator弹簧动画
关于绘图和动画有两种处理的方式:CPU(中央处理器)和GPU(图形处理器)。在现代iOS设备中,都有可以运行不同软件的可编程芯片,但是由于历史原因,我们可以说CPU所做的工作都在软件层面,而GPU在硬件层面。
总的来说,我们可以用软件(使用CPU)做任何事情,但是对于图像处理,通常用硬件会更快,因为GPU使用图像对高度并行浮点运算做了优化。由于某些原因,我们想尽可能把屏幕渲染的工作交给硬件去处理。问题在于GPU并没有无限制处理性能,而且一旦资源用完的话,性能就会开始下降了(即使CPU并没有完全占用)。
1. UIView动画
在UIView类中共有三个类目(Category)用于实现动画功能,分为UIViewAnimation、UIViewAnimationWithBlocks以及UIViewKeyframeAnimations,他们是对核心动画(Core Animation)的封装,可以让我们不进行任何绘画等复杂操作的前提下实现大部分动画需求
UIView动画就是利用UIView的API来实现动画效果。而利用UIView API也可以分为两种,一种block形式,一种多API组合。
一、一般形式的UIView动画
#pragma mark - 一般形式的UIView动画
- (void)baseViewAnimation
{
[UIView beginAnimations:@"centerAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:@selector(animationWillStart)];
[UIView setAnimationDidStopSelector:@selector(animationDidStop)];
self.testView.center = CGPointMake(K_width/2, 64);
[UIView commitAnimations];
}
- (void)animationWillStart
{
self.testView.transform = CGAffineTransformMakeScale(0.2, 0.2);
}
- (void)animationDidStop
{
self.testView.transform = CGAffineTransformIdentity;;
}
二、block形式的UIView动画
在animations block中只能修改UIView的部分属性,产生动画效果。而可以产生动画效果的属性,苹果在其注释中都有标记 animatable。
1. 最简单的UIView动画API
第一个参数是动画执行时长(单位:秒);第二个参数就是动画的block,属性变化信息的最终值。
[UIView animateWithDuration:3.0 animations:^{
self.testView.frame = CGRectMake(50, 50, 100, 100);
}];
2. 比方法1多了一个延迟时间(单位:秒)和动画类型
延迟时间是表示多久之后执行该动画,动画执行类型有样式,比如速度先快后慢,开始快中间慢结束时再快,匀速等等。可以移除设置不同的枚举值来比较。
#pragma mark - block形式的UIView动画
- (void)blockAnimation_1
{
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.testView.center = CGPointMake(K_width/2, K_height-self.testView.bounds.size.height/2);
} completion:^(BOOL finished) {
[self.testView removeFromSuperview];
}];
}
3. 弹性动画
像橡皮筋一样,将试图改变至属性所设置的值后,会有一个回弹效果。根据设置的初速度和阻尼系数慢慢停止,最终停留在属性所设置的值的状态。
相比于方法2,多了一个damping阻尼系数和初速度
- (void)blockAnimation_2 // 弹性动画
{
/*
usingSpringWithDamping: 震动效果,取值范围在0.0~1.0, 取值越小,震荡幅度越大
initialSpringVelocity:初始速度,数值越大初始速度越快。确定了在动画结束之前运动的速度。一般情况下都是设置为0。设值举个例子来说,如果想要移动的距离为200pt,移动速度为100pt/s,就需要设置为0.5。
options:动画的过渡效果
*/
[UIView animateWithDuration:2 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.testView.center = CGPointMake(K_width/2, K_height-self.testView.bounds.size.height/2-10);
} completion:^(BOOL finished) {
}];
}
4. 关键帧动画
UIView动画现在只支持属性关键帧动画,不支持路径关键帧动画
[UIView animateKeyframesWithDuration:(NSTimeInterval)//动画持续时间
delay:(NSTimeInterval)//动画延迟执行的时间
options:(UIViewKeyframeAnimationOptions)//动画的过渡效果
animations:^{
//执行的关键帧动画
}
completion:^(BOOL finished) {
//动画执行完毕后的操作
}];
增加关键帧的方法:
[UIView addKeyframeWithRelativeStartTime:(double)//动画开始的时间(占总时间的比例)
relativeDuration:(double) //动画持续时间(占总时间的比例)
animations:^{
//执行的动画
}];
具体实现方法
- (void)blockAnimation_3 // 关键帧动画
{
[UIView animateKeyframesWithDuration:5 delay:0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionCurveLinear animations:^{
//第一个关键帧:从0秒开始持续50%的时间,也就是5.0*0.5=2.5秒
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
self.testView.center = CGPointMake(K_width/2, K_height-self.testView.bounds.size.height/2-10);
}];
//第二个关键帧:从50%时间开始持续25%的时间,也就是5.0*0.25=1.25秒
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
self.testView.center = CGPointMake(0, 0);
}];
//第三个关键帧:从75%时间开始持续25%的时间,也就是5.0*0.25=1.25秒
[UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
self.testView.center = CGPointMake(K_width/2, K_height/2);
}];
} completion:^(BOOL finished) {
}];
}
关键帧动画的options多了一些选择
/* 动画模式选择,选择一个 */
UIViewKeyframeAnimationOptionCalculationModeLinear/*< 连续运算模式 */
UIViewKeyframeAnimationOptionCalculationModeDiscreter/*< 离散运算模式 */
UIViewKeyframeAnimationOptionCalculationModePacedr/*< 均匀执行运算模式 */
UIViewKeyframeAnimationOptionCalculationModeCubicr/*< 平滑运算模式 */
UIViewKeyframeAnimationOptionCalculationModeCubicPacedr/*< 平滑均匀运算模式 */
5. 转场动画
第一种:单个视图的过渡效果
- (void)transitionWithView_4 // 转场动画
{
/*
以上方式可以在改变视图的属性时产生动画,如果视图添加或者移除的时候想要添加动画,就要用到下面的方式了
*/
UIViewAnimationOptions option = UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft;
[UIView transitionWithView:self.imageview duration:10.0 options:option animations:^{
UIImage *image = [UIImage imageNamed:@"maskImage"];
self.imageview.image = image;
} completion:^(BOOL finished) {
}];
}
转场动画options多了一些选择:
/* 转场类型 */
UIViewAnimationOptionTransitionNone/*< 没有转场动画效果 */
UIViewAnimationOptionTransitionFlipFromLeft/*< 从左侧翻转效果 */
UIViewAnimationOptionTransitionFlipFromRight/*< 从右侧翻转效果 */
UIViewAnimationOptionTransitionCurlUp/*< 向后翻页的动画过渡效果 */
UIViewAnimationOptionTransitionCurlDown/*< 向前翻页的动画过渡效果 */
UIViewAnimationOptionTransitionCrossDissolve/*< 溶解消失效果 */
UIViewAnimationOptionTransitionFlipFromTop/*< 从上方翻转效果 */
UIViewAnimationOptionTransitionFlipFromBottom/*< 从底部翻转效果 */
第二种:两个视图之间转场可以使用,从旧视图转到新视图的动画效果
默认情况,转出的视图会从父视图移除,转入后重新添加在该动画过程中,fromView 会从父视图中移除,并讲 toView 添加到父视图中,注意转场动画的作用对象是父视图(过渡效果体现在父视图上)。
- (void)transitionWithView_5 // 转场动画
{
/*
这是一个便捷的视图过渡 API,在动画过程中,首先将 fromView 从父视图中删除,然后将 toView 添加,就是做了一个替换操作。
在需要视图更改时,这个将变得特别有用。
*/
UIViewAnimationOptions option = UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft;
[UIView transitionFromView:self.testView toView:self.imageview duration:5 options:option completion:^(BOOL finished) {
}];
}
调用该方法相当于执行下面两句代码:
[fromView.superview addSubview:toView];
[fromView removeFromSuperview];
2. Core Animation
定义:
Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
Core Animation 是跨平台的,可以用在Mac OS X 和iOS 平台。
Core Animation 的动画执行过程都是在后台操作的,不会阻塞主线程。不阻塞主线程,可以理解为在执行动画的时候还能点击(按钮)。
要注意的是,Core Animation 是直接作用在 CALayer 上的,并非UIView,iOS 的 UIView 背后都有一个对应的 CALayer。对 UIView 的修改实际上都是对背后 CALayer 的修改。
当 CALayer 在背后支持一个 UIView 的时候,UIView 就是它的 delegate。即,UIView 是 CALayer 的CALayerDelegate。
即 Core Animation 不改变 UIView 的 Frame 属性,也就是说并不改变 UIView 的实际位置。
图层树和模型树
CALayer 的同一个属性值,会分别保存在模型层 modelLayer ,和展现层 presentationLayer 中。当我们修改属性值时,是修改的模型层的数值,动画时系统根据模型层的变化,生成的过渡值,是保存在展现层中的。
在CALayer 的对象里能直接访问到这两层的信息。而CALayer 的底层实现实际不止这两层,但我们现在讨论动画的时候,可以只关心这两层。
在整个动画过程中,呈现出来的过程是这样的:
动画前,显示模型层的当前值;
动画开始,切换显示展现层的值;
动画过程中,展现层的值根据时间变化,我们看到的实际是展现层的值在变化;
动画结束,切换回显示模型层的值,此时模型层的值应被修改为动画结束时的值。
由于在动画过程中,修改的只是展现层的值,模型层的值并没有改变,所以Core Animation 并不修改 UIView 的实际位置。(如果要修改UIView 的实际位置,则要手动修改 UIView 的 Frame)
UIKit动画和Core Animation
UIKit实现的动画效果往往都可以满足你对动画的需求,而且实现代码非常简单,就像Core Animation的隐式动画一样,只需要在UIKit事务中修改相应可动画属性即可,所以,一般情况下UIKit动画是你优先选择的方式,但这里有一个误区,有很多人在讲述iOS动画的时候,会把UIKit动画和Core Animation动画定义成两种完全不同的处理方式,并且认为Core Animation动画的性能会更优一些,但事实并非如此,UIKit动画和Core Animation动画是相关连的。
UIKit虽然提供了非常简便的API来实现动画,但UIKit动画毕竟是Core Animation动画的一个抽象物,能提供的效果还是很有限的。
UIKit动画其内部实现是Core Animation动画。UIView对象的rootlayer的隐式动画是默认关闭的。
显式动画和隐式动画
Core Animation动画有两种形式,分别是显式动画和隐式动画,但不管以哪种形式实现动画,都是基于CAAnimation来实现的,所以这两种动画形式的主要差异在于,是否显式创建CAAnimation对象来实现动画,当然它们还存在其它的差异,例如,隐式动画是基于CABasicAnimation对来实现的,而显式动画可以有更多的选择,可以是CABasicAnimation,CAKeyframeAnimation,CATransition等。
对于独立CALayer而言,隐式动画是默认开启的,只需要更改可动画属性就会触发隐式动画,但对于UIView的rootlayer而言,隐式动画是默认关闭的。
虽然隐式动画的大部份参数由CATransaction来决定,显式创建CATransaction常常被用于关闭隐式动画(独立的CALayer对象默认开启隐式动画,需要手动关闭)和调整动画的时间。
Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。Core Animation是直接作用在CALayer上的,并非UIView。
CAAnimation注意要点:
- 能用的动画类只有4个子类:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup;
- CAMediaTiming是一个协议(protocol),CAMediaTiming媒体时间类协议解析:
1.beginTime 动画开始的时间默认为0;
2.duration 动画的持续时间,默认为0 ,持续时间受速度的影响 实际动画完成时间 = 持续时间/速度;
3.speed 动画的播放速度 ,默认为1 ,速度设置为0 ,可以暂停动画。如果speed=2 , duration =60 那么动画真正播放完成的时间 30秒;
4.timeOffset 动画播放时间的偏移量;
5.repeatCount 动画的循环次数 默认是0 只播放一次;
6.repeatDuration 动画循环的持续时间,
repeatCount/repeatDuration 只能设置其中的一个属性;
7.autoreverses 是否以动画的形式返回 返回到播放之前的状态;
8.fillMode 动画填充模式,设置当前对象在非活动时间段的状态,
要想fillMode有效 需设置removedOnCompletion = NO;
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 立即进入动画的初始状态并等待动画开始
kCAFillModeBoth 动画加入后开始之前 layer处于动画初始状态 动画结束后layer保持动画最后的状态
kCAFillModeRemoved 默认值 动画结束后 layer会恢复到之前的状态
CAAnimation动画属性方法介绍:
- 初始化的方法 animation
- timingFunction 速度控制函数,控制动画运行的节奏
timingFunction的初始化方法: functionWithName:
kCAMediaTimingFunctionLinear 线性,匀速
kCAMediaTimingFunctionEaseIn 慢进后快
kCAMediaTimingFunctionEaseOut 快进后慢
kCAMediaTimingFunctionEaseInEaseOut 先慢进后快再慢出
kCAMediaTimingFunctionDefault 实际效果是动画中间比较快
- removedOnCompletion 完成动画的时候 是否移除动画效果 默认为YES
- 代理方法:
-(void)animationDidStart:(CAAnimation *)anim
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
CAAnimation子类:
- CAAnaimation和CAPropertyAnimation是个抽象类,不具备动画效 果,必须用它们的子类才有动画效果;
- CABasicAnimation基本动画,做一些简单效果;
- CAKeyframeAnimation帧动画,做一些连续的流畅的动画;
- CAAnimationGroup是个动画组,可以同时进行缩放,旋转。
- CATransition是转场动画,界面之间跳转都可以用转场动画。
1. CABasicAnimation 基础动画
CABasicAnimation用来创建基于两个状态的动画,你只需要给出两个状态,一个初始状态一个终止状态,系统自动为你将中间的动画补全。
通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation.
CABasicAnimation动画主要是设置某个动画属性的初始值fromValue和结束值toValue,来产生动画效果。
创建CABasicAnimation 的方法,但是在最新的apple开发文档没有查到path到底有哪些,网上搜罗了一下,并猜测path跟layer中的属性字段是一致的如background。
基于CAPropertyAnimation的属性动画,可以更改属性,二级属性也可以去做动画。
| path | 用途
| -------------
| rotaion.x | 旋转,弧度,X轴
| rotaion.y | 旋转,弧度,Y轴
| rotaion.z | 旋转,弧度,Z轴
| rotaion | 旋转,弧度,Z轴,完全等同于rotation.z
| scale.x | 缩放,X轴
| scale.y | 缩放,Y轴
| scale.z | 缩放,Z轴
| scale | 缩放,XYZ轴
| translation.x | 移动,X轴
| translation.y | 移动,Y轴
| translation.z | 移动,Z轴
| translation | 移动,XY轴,value值为NSSize或者CGSize类型
| opacity等 | zPosition、frame、backgroundColor、cornerRadius类似的layer中的各种属性
Animation的几个属性:
animationWithKeyPath:动画的创建使用animationWithKeyPath: 因为使用的keyPath所以动画属性或者其结构体中元素都可以产生动画;
duration: 动画的时长;
fromValue和toValue: 是CABasicAnimation的属性,都是id类型的,所以要将基本类型包装成对象;
removedOnCompletion: 决定动画执行完之后是否将该动画的影响移除,默认是YES,则layer回到动画前的状态;是否在播放完成后移除。这是一个非常重要的属性,有的时候我们希望动画播放完成,但是保留最终的播放效果是,这个属性一定要改为NO,否则无效。
fillMode: 是个枚举值(四种),当removedOnCompletion设置为NO之后才会起作用。可以设置layer是保持动画开始前的状态还是动画结束后的状态,或是其他的;
autoreverses: 表示动画结束后是否 backwards(回退) 到动画开始前的状态。可与上面两个属性组合出不同效果。
timingFunction: 动画的运动是匀速线性的还是先快后慢等,类似UIView动画的opitions。另外,CAMediaTimingFunction 方法可以自定义。
delegate 代理:两个动画代理方法:
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
添加/移除动画方法
给某个layer添加动画
- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key;
与之对应的移除某个动画是
- (void)removeAnimationForKey:(NSString *)key;
#pragma mark - CABasicAnimation-基础动画:位移、透明度、缩放、旋转
/**
* 透明度动画
*/
-(void)opacityAniamtion{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"opacity"];
//fromValue和toValue都是id类型的,所以要将基本类型包装成对象
anima.fromValue = [NSNumber numberWithFloat:1.0f];
anima.toValue = [NSNumber numberWithFloat:0.2f];
anima.duration = 1.0f; //动画的时长
//决定动画执行完之后是否将该动画的影响移除,默认是YES,则layer回到动画前的状态
anima.removedOnCompletion = NO;
//是个枚举值(四种),当removedOnCompletion设置为NO之后才会起作用。可以设置layer是保持动画开始前的状态还是动画结束后的状态,或是其他的
anima.fillMode = kCAFillModeForwards;
//表示动画结束后是否 backwards(回退) 到动画开始前的状态。可与上面两个属性组合出不同效果。
//anima.autoreverses = YES;
//动画的运动是匀速线性的还是先快后慢等,类似UIView动画的opitions。另外,CAMediaTimingFunction 方法可以自定义。
anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anima.delegate = self;//设置代理,可以检测动画的开始和结束
[self.testView.layer addAnimation:anima forKey:@"opacityAniamtion"];
}
/**
* 缩放动画
*/
-(void)scaleAnimation{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.scale"];//同上
anima.toValue = [NSNumber numberWithFloat:2.0f];
anima.duration = 1.0f;
anima.removedOnCompletion = NO;
anima.fillMode = kCAFillModeForwards;
[self.testView.layer addAnimation:anima forKey:@"scaleAnimation"];
}
/**
* 旋转动画
*/
-(void)rotateAnimation{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];//绕着z轴为矢量,进行旋转(@"transform.rotation.z"==@@"transform.rotation")
anima.toValue = [NSNumber numberWithFloat:3*M_PI];
anima.duration = 1.0f;
[self.testView.layer addAnimation:anima forKey:@"rotateAnimation"];
}
/**
* 背景色变化动画
*/
-(void)backgroundAnimation{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
anima.toValue =(id) [UIColor greenColor].CGColor;
anima.duration = 1.0f;
[self.testView.layer addAnimation:anima forKey:@"backgroundAnimation"];
}
2. CAKeyframeAnimation 关键帧动画
Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动 CAKeyframeAnimation 的一些比较重要的属性。所以CAKeyframeAnimation也是根据属性展示动画的,他与CABasicAnimation的不同点在于他可以指定多个状态,不局限于始末状态,这样你的动画将更加灵活。
CAKeyframeAnimation我们一般称为关键帧动画,主要是利用其values属性,设置多个关键帧属性值,来产生动画。
对比UIView动画跟关键帧动画,关键帧动画引入了动画占比时长的概念,这让我们能控制每个关键帧动画的占用比例而不是传入一个无意义的动画时长 —— 这让我们的代码更加难以理解。当然,除了动画占比之外,关键帧动画的options参数也让动画变得更加平滑。
2.1. path
这是一个 CGPathRef 对象,默认是空的,当我们创建好CAKeyframeAnimation的实例的时候,可以通过制定一个自己定义的path来让某一个物体按照这个路径进行动画。这个值默认是nil,当其被设定的时候values 这个属性就被覆盖。
/**
* path动画
*/
-(void)pathAnimation{
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;
anima.removedOnCompletion = NO;
anima.fillMode = kCAFillModeForwards;
[_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
}
2.2. values
一个数组,提供了一组关键帧的值,当使用path的 时候 values的值自动被忽略。
-(void)keyframeAnimation{
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
keyAnimation.duration = 1.0f;
//CAAnimation类的属性,可以设置动画延迟多久执行,示例代码是延迟1秒执行。
keyAnimation.beginTime = CACurrentMediaTime() + 1.0;
CATransform3D transform1 = CATransform3DMakeScale(1.5, 1.5, 0);
CATransform3D transform2 = CATransform3DMakeScale(0.8, 0.8, 0);
CATransform3D transform3 = CATransform3DMakeScale(3, 3, 0);
//是CAKeyframeAnimation的属性,设置keyPath属性在几个关键帧的值,也是id类型的。
keyAnimation.values = @[[NSValue valueWithCATransform3D:transform1],[NSValue valueWithCATransform3D:transform2],[NSValue valueWithCATransform3D:transform3]];
//是CAKeyframeAnimation的属性,每个值对应相应关键帧的时间比例值。keyTimes属性指定的是当前状态节点到初始状态节点的时间占动画总时长的比例。若果不设置keyTimes则匀速播放
keyAnimation.keyTimes = @[@0,@0.5,@1];
//是CAKeyframeAnimation的属性,对应每个动画段的动画过渡情况;而timingFunction是CAAnimation的属性。
keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
keyAnimation.removedOnCompletion = NO;
keyAnimation.fillMode = kCAFillModeForwards;
[self.testView.layer addAnimation:keyAnimation forKey:nil];
}
3. CAAnimationGroup 组合动画
Group也就是组合的意思,可以保存一组动画对象,CAAnimationGroup的animations中可以放其他任何动画类(包括CAAnimationGroup),将CAAnimationGroup对象加入图层后,组中所有动画对象可以同时并发运行。
animations属性:用来保存一组动画对象的NSArray
注意:
- animations里的单个动画,当单个动画设置了duration之后动画可能会有不同,一般里面不设置,在最外层设置group的duration即可。
- 默认情况下,一个layer设定了很多动画,他们都会同时执行,而且是顺序执行,也可以通过设置动画对象的beginTime属性来更改动画的开始时间
-(void)groupAnimation1{
// //位移动画
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"];
}
4. CATransition 系统封装的过渡动画
CATransition动画就是动画效果和方向的结合,以下为重要属性
type:动画过渡类型
Apple 官方的SDK其实只提供了四种过渡效果,都支持方向设置:
kCATransitionFade 淡出效果
kCATransitionMoveIn 新视图移动到旧视图上
kCATransitionPush 新视图推出旧视图
kCATransitionReveal 移开旧视图显示新视图
私有API提供了其他很多非常炫的过渡动画,其中部分支持方向设置,比如:
@"cube":立方体翻转效果
@"suckEffect":收缩效果
@"oglFlip":翻转效果
@"rippleEffect":水滴波纹效果
@"pageCurl":向上翻页效果
@"pageUnCurl":向下翻页效果
@"cameraIrisHollowOpen":摄像头打开效果
@"cameraIrisHollowClose":摄像头关闭效果
注意:私有api,不建议开发者们使用。因为苹果公司不提供维护,并且有可能造成你的app审核不通过。
subtype:动画过渡方向
kCATransitionFromRight 从右侧进入
kCATransitionFromLeft 从左侧进入
kCATransitionFromTop 从顶部进入
kCATransitionFromBottom 从底部进入
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)
写法一
#pragma mark - CATransition:转场动画:淡入淡出、推挤、解开、覆盖
-(void)transitionAnimation
{
/*
什么是转场动画?
就是从一个场景转换到另外一个场景,像导航控制器的push效果,就是一个转场。能为层提供移除屏幕和移入屏幕的动画效果
CATransition通常用于通过CALayer控制UIView内子控件的过渡动画,比如删除子控件,添加子控件,切换两个子控件等。
imageView切换图片,控制器的push或modal,UIView对象调用exchangeSubviewAtIndex:WithIndex:方法的时候可以出发转场动画.
基本使用
创建CATransition对象。
为CATransition设置type和subtype两个属性,type指定动画类型,subtype指定动画移动方向(有些动画是固定方向,指定subtype无效)。
如果不需要动画执行整个过程(动画执行到中间部分就停止),可以指定startProgress,endProgress属性。
调用UIView的layer属性的addAnimation: forKey:方法控制该UIView内子控件的过渡动画。
动画类型:
CATransition的type有以下几个值
kCATransitionFade 渐变
kCATransitionMoveIn 覆盖
kCATransitionPush 推出
kCATransitionReveal 揭开
除此之外,该type还支持如下私有动画
cube 立方体旋转
suckEffect 收缩动画
oglFlip 翻转
rippleEffect 水波动画
pageCurl 页面揭开
pageUnCurl 放下页面
cemeraIrisHollowOpen 镜头打开
cameraIrisHollowClose 镜头关闭
CATransition的subtype属性用于控制动画方向,支持如下值
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom
*/
//创建一个转场动画
CATransition *animation = [CATransition animation];
animation.beginTime = CACurrentMediaTime() + 1.0;
animation.duration = 5;
//设置转场类型
//animation.type = kCATransitionMoveIn;
animation.type = @"oglFlip";
//设置转场的方向
animation.subtype = kCATransitionFromTop;
//设置动画开始的位置
//animation.startProgress = 0.5;
//设置动画结束的位置
//animation.endProgress = 0.8;
UIImage *image = [UIImage imageNamed:@"maskImage"];
self.imageview.image = image;
//添加动画
[self.imageview.layer addAnimation:animation forKey:@"transitionAnimation"];
}
写法二
-(void)test
{
[UIView beginAnimations:@"animationID" context:nil];
[UIView setAnimationDuration:0.5f]; //动画时长
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES]; //给视图添加过渡效果
//在这里写你的代码.
[UIView commitAnimations]; //提交动画
}
#pragma UIView实现动画
- (void) animationWithView : (UIView *)view WithAnimationTransition : (UIViewAnimationTransition) transition
{
[UIView animateWithDuration:DURATION animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:transition forView:view cache:YES];
}];
}
3. 自定义转场动画
非交互式的转场动画
目前为止,官方支持以下几种方式的自定义转场:
在 UINavigationController 中 push 和 pop;
在 UITabBarController 中切换 Tab;
Modal 转场:presentation 和 dismissal,俗称视图控制器的模态显示和消失,仅限于modalPresentationStyle属性为 UIModalPresentationFullScreen 或 UIModalPresentationCustom 这两种模式;
UICollectionViewController 的布局转场:UICollectionViewController 与 UINavigationController 结合的转场方式,实现很简单。
转场代理(Transition Delegate)
这个协议要求我们实现两个方法,其中一个定义了动画的持续时间:
另一个方法描述整个动画的执行效果:
方法中获取 transition context,从 transition context 中得到了需要做转场的两个 view controller,然后可以使用最简单的 UIView animation 来实现转场动画
交互式的转场动画