在iOS开发中,动画是提高用户体验重要的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,这对于app而言是非常重要的。
iOS动画主要是指Core Animation框架。官方使用文档地址为:Core Animation Guide。Core Animation是iOS和macOS平台上负责图形渲染与动画的基础框架。Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作。你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用Core Animation的动画效果。Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且显示效果更加平滑,不会加重CPU的负担而影响程序的运行速度。
Core Animation是一组非常强大的动画处理API,它的子类主要有4个:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup。 Core Animation类的继承关系图:
duration:动画的持续时间 beginTime:动画的开始时间 repeatCount:动画的重复次数 autoreverses:动画按照原动画返回执行 timingFunction:控制动画的显示节奏系统提供五种值选择,分别是:
delegate:动画代理。能够检测动画的执行和结束。 path:帧动画中的执行路径 type:过渡动画的动画类型。主要有以下4中类型:
subtype:过渡动画的动画方向。
动画使用步骤:
CALayer中很多属性都可以通过CAAnimation实现动画效果, 包括opacity, position, transform, bounds, contents等,具体可以在API文档中查找
通过调用CALayer的addAnimation:forKey:增加动画到层(CALayer)中,这样就能触发动画了.通过调用removeAnimationForKey:可以停止层中的动画.
_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"];
基础动画主要提供了对于CALayer对象中的可变属性进行简单动画的操作。比如:位移、透明度、缩放、旋转、背景色等等。 主要提供如下属性: fromValue:keyPath对应的初始值 toValue:keyPath对应的结束值 示例:
1.呼吸动画
CABasicAnimation *animation =[CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];
animation.autoreverses = YES; //回退动画(动画可逆,即循环)
animation.duration = 1.0f;
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;//removedOnCompletion,fillMode配合使用保持动画完成效果
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self.alphaTagButton.layer addAnimation:animation forKey:@"aAlpha"];
2.摇摆动画
//设置旋转原点
self.sharkTagButton.layer.anchorPoint = CGPointMake(0.5, 0);
CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
//角度转弧度(这里用1,-1简单处理一下)
rotationAnimation.toValue = [NSNumber numberWithFloat:1];
rotationAnimation.fromValue = [NSNumber numberWithFloat:-1];
rotationAnimation.duration = 1.0f;
rotationAnimation.repeatCount = MAXFLOAT;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.autoreverses = YES;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotationAnimation.fillMode = kCAFillModeForwards;
[self.sharkTagButton.layer addAnimation:rotationAnimation forKey:@"revItUpAnimation"];
注意: 如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。这就相当于Android早期的View动画。
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没有设置的时候,各个关键帧的时间是平分的。 示例:
values属性应用
-(void)setUpCAKeyframeAnimationUseValues
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, 50)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, kWindowHeight-50)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, kWindowHeight-50)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
animation.values = @[value1,value2,value3,value4,value5];
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 6.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.keyButton.layer addAnimation:animation forKey:@"values"];
}
path方式应用
-(void)setUpCAKeyframeAnimationUsePath
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
CGMutablePathRef path = CGPathCreateMutable();
//矩形线路
CGPathAddRect(path, NULL, CGRectMake(50,50, kWindowWidth - 100,kWindowHeight - 100));
animation.path=path;
CGPathRelease(path);
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 10.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.keyButton.layer addAnimation:animation forKey:@"path"];
}
keyTimes属性使用
-(void)setUpCAKeyframeAnimationUsekeyTimes
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position.x";
animation.values = @[@0, @20, @-20, @20, @0];
animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
animation.duration = 0.5;
animation.additive = YES;
[self.sharkTagButton.layer addAnimation:animation forKey:@"keyTimes"];
}
CAAnimationGroup(组动画)是CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行。有点类似于Android的帧动画,不过这里的组动画是将一些基础的动画拼接而成的,比如同时缩小、旋转、渐变。
主要属性有: animations:用来保存一组动画对象的NSArray。 示例:
CABasicAnimation * animationScale = [CABasicAnimation animation];
animationScale.keyPath = @"transform.scale";
animationScale.toValue = @(0.1);
CABasicAnimation *animationRota = [CABasicAnimation animation];
animationRota.keyPath = @"transform.rotation";
animationRota.toValue = @(M_PI_2);
CAAnimationGroup * group = [[CAAnimationGroup alloc] init];
group.duration = 3.0;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.repeatCount = MAXFLOAT;
group.animations = @[animationScale,animationRota];
[self.groupButton.layer addAnimation:group forKey:nil];
CAAnimation的子类,用于做过渡动画或者转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。 重要属性有: type:动画过渡类型,官方提供了如下类型:
subtype:动画过渡方向。
示例:
MyViewController *myVC = [[MyViewController alloc]init];
CATransition *animation = [CATransition animation];
animation.timingFunction = UIViewAnimationCurveEaseInOut;
animation.type = @"cube";
animation.duration =0.5f;
animation.subtype =kCATransitionFromRight;
//控制器间跳转动画
[[UIApplication sharedApplication].keyWindow.layer addAnimation:animation forKey:nil];
[self presentViewController:myVC animated:NO completion:nil];