IOS动画
动画提供了界面不同状态间的连续虚拟变换,在iOS中动画可以用于重新配置视图,改变大小,改变层级,隐藏他们等等。
其中动画有两个级别的操作方式,UIKit Animation用于UIView对象,其封装了Core Animation,而Core Animation用于CALayer层对象,操作更加底层。
哪些对象可以用于动画?
UIKit Animation可以修改UIView属性有:
frame,即改变视图的大小和位于父视图的位置
bounds,修改视图的大小
center,修改位于父视图的位置
transform,视图的缩放、旋转,只能在2D界面变化
alpha,修改视图的透明度
backgroundColor,修改视图的背景色
contentStretch,修改视图的拉伸
Core Animation可以修改CALayer属性有:
layer的大小和位置
layer的center点
layer的3D变换
layer的层级变换
layer的阴影
layer的边框
layer的一部分的拉伸变换
layer的不透明度
layer剪切超出边界的部分
layer的contents
layer的光栅
UIKit Animation
使用基于Block的方法
animateWithDuration:animations:animateWithDuration:delay:options:animations:completion:
例子:
[UIView animateWithDuration:1.0 animations:^{
firstView.alpha = 0.0;
secondView.alpha = 1.0;
}];
animateWithDuration:animations:completion:
例子:
// Fade out the view right away
[UIView animateWithDuration:1.0
delay: 0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
thirdView.alpha = 0.0;
}
completion:^(BOOL finished){
// Wait one second and then fade in the view
[UIView animateWithDuration:1.0
delay: 1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
thirdView.alpha = 1.0;
}
completion:nil];
}];
使用基于Begin/Commit的方法
该方法用于ios3.2及之前版本,4.0及之后版本需要使用block方式。
[UIView beginAnimations:@"ToggleViews" context:nil];
[UIView setAnimationDuration:1.0];
// Make the animatable changes.
firstView.alpha = 0.0;
secondView.alpha = 1.0;
// Commit the changes and perform the animation.
[UIView commitAnimations];
Core Animation
Core Animation基础
动画层级图
动画可操作修改的属性 Layer对象的坐标系统
layer使用了两套坐标系统,
第一套为使用编程点定义的坐标系统,也是平时编程中使用最多的坐标 第二套为单元坐标系统,犹如以前数学学习时常将坐标换算到单位坐标系[0,1]进行计算 前者较后者用于精度要求高的场景。
Anchor Points的含义 锚点的含义是指,当我们对一个视图定义时,视图中的其它元素均相对于此点进行相对计算。 Layer Trees简介
Layer是通过tree的结构组织起来,共有三种Layer tree
model layer tree
presentation tree
render tree
model Layer tree中的Layer是我们通常意义说的Layer。当我们修改layer中的属性时,就会立刻修改model layer tree。
layer.position = CGPointMake(0,0); //这里的修改会直接影响model layer tree
presentation tree是Layer在屏幕中的真实位置。比如我们创建一个动画
[UIView animateWithDuration:5.0f
animations:^{
self.animationLabel.center = CGPointMake(200, 400);
}];
//这里用一个Timer print presentLayer的位置。
CALayer *layer = self.animationLabel.layer.presentationLayer;
NSLog(@"model:%@, presentLayer%@", NSStringFromCGPoint(self.animationLabel.layer.position), NSStringFromCGPoint(layer.position));
下面是屏幕输出结果
model:{73.5, 155.5}, presentLayer{73.5, 155.5}
model:{200, 400}, presentLayer{73.559769, 155.61552}//开始动画
model:{200, 400}, presentLayer{73.814095, 156.10709}
model:{200, 400}, presentLayer{74.267357, 156.98315}
...
...
...
model:{200, 400}, presentLayer{199.99576, 399.99182}
model:{200, 400}, presentLayer{200, 400}
render tree 在apple的render server进程中,是真正处理动画的地方。而且线程的优先级也比我们主线程优先级高。所以有时候即使我们的App主线程busy,依然不会影响到手机屏幕的绘制工作。(参考)
Core Animation使用
动画类的继承关系 CAAnimation
其中,CAAnimation是抽象基类,支持CAMediaTiming和 CAAction,其他动画类均继承自此类。 常见属性有:
duration
,动画持续的时间;
repeatCount
,动画重复的次数;
timingFunction
,控制动画运行,包括kCAMediaTimingFunctionLinear
,kCAMediaTimingFunctionEaseIn
,kCAMediaTimingFunctionEaseOut
,kCAMediaTimingFunctionEaseInEaseOut
(渐进渐出为默认值)
delegate
代理方法有
- (void)animationDidStart:(CAAnimation *)theAnimation
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
CAPropertyAnimation
CAPropertyAnimation是CAAnimation的子类,但是不能直接使用,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
CABasicAnimation
CABasicAnimation类的使用方式就是基本的关键帧动画。
所谓关键帧动画,就是将Layer的属性作为KeyPath来注册,指定动画的起始帧和结束帧,然后自动计算和实现中间的过渡动画的一种动画方式。
CABasicAnimation使用例子:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 2.5; // 动画持续时间
animation.repeatCount = 1; // 不重复
animation.beginTime = CACurrentMediaTime() + 2; // 2秒后执行
animation.autoreverses = YES; // 结束后执行逆动画
// 动画先加速后减速
animation.timingFunction =
[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
/ 设定动画起始帧和结束帧
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)]; // 起始点
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(320, 480)]; // 终点
[myView.layer addAnimation:animation forKey:@"move-layer"];
// 动画终了后不返回初始状态
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
CAKeyframeAnimation
如果是简单的动画CABasicAnimation就能完成,CAKeyframeAnimation(关键帧动画)弥补了基本动画只能传入一对对应值的不足,关键帧动画支持传入一套数值或一个路径来完成动画。
//例子demoView左右摇摆
self.demoView.layer.anchorPoint = CGPointMake(0.5, 0.0);
CAKeyframeAnimation *animaiton = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
NSArray *rotationVelues = @[@(M_PI_4), @(-M_PI_4), @(M_PI_4)];
animaiton.values = rotationVelues;
animaiton.duration = 3.0f;
animaiton.repeatCount = 10000;
[self.demoView.layer addAnimation:animaiton forKey:nil];
使用贝塞尔路径:
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:self.demoView.center];
[path addCurveToPoint:CGPointMake(270, 410) controlPoint1:CGPointMake(0, Screen_Height) controlPoint2:CGPointMake(Screen_Width, 0)];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.path = path.CGPath;
animation.duration = 3.0f;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.demoView.layer addAnimation:animation forKey:nil];
CAAnimationGroup
动画组将多个动画组合后使用,在其设定运行时间内执行多个动画,当某单个动画的时间超过动画组的时间时,按动画组设定的时间截取。
/* 动画1(在X轴方向移动) */
CABasicAnimation *animation1 =
[CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
// 终点设定
animation1.toValue = [NSNumber numberWithFloat:80];; // 終点
/* 动画2(绕Z轴中心旋转) */
CABasicAnimation *animation2 =
[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
// 设定旋转角度
animation2.fromValue = [NSNumber numberWithFloat:0.0]; // 开始时的角度
animation2.toValue = [NSNumber numberWithFloat:44 * M_PI]; // 结束时的角度
/* 动画组 */
CAAnimationGroup *group = [CAAnimationGroup animation];
// 动画选项设定
group.duration = 3.0;
group.repeatCount = 1;
// 添加动画
group.animations = [NSArray arrayWithObjects:animation1, animation2, nil nil];
[myView.layer addAnimation:group forKey:@"move-rotate-layer"];
CATransition CATransition实现了过渡动画
/*
NSString *types[4] = {kCATransitionMoveIn, kCATransitionPush, kCATransitionReveal, kCATransitionFade};
NSString *subtypes[4] = {kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom};
//立方 吸走 翻转 水波 翻页 翻页回
NSString *moreTypes[]={@"cube",@"suckEffect",@"oglFlip",@"rippleEffect",@"pageCurl",@"pageUnCurl",@"cameraIrisHollowOpen",@"cameraIrisHollowClose"};
*/
CATransition *animation = [CATransition animation];
[animation setDuration:0.4];
[animation setType: @"fade"];
[animation setSubtype: kCATransitionFromRight];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[self.navigationController.view.layer addAnimation:animation forKey:nil];
[self.navigationController popViewControllerAnimated:NO];
http://www.nohackcc.com/2015/01/22/iosdong-hua-zong-shu/