粉骨碎身全不怕, 要留清白在人间!<小拳石>动画的思维导图
基础知识:
iOS能够实现动画的方式:(如上图)
- UIView基础实现方式一
- UIView基础实现方式二
- CoreAnimation实现方式
动画的效果简述:
- 传达状态
- 提高用户对直接操作的感知
- 帮助用户可视化操作的结果
UIVIew 的基础动画:
- UIKit直接将动画继承到UIView类中, 当内部的一些属性发生改变时, UIView将为这些改变提供动画支持.
- 执行动画的工作由UIView类自动完成, 但希望在执行动画时通知视图, 为此需要将改变属性的代码放在
[UIView beginAnimations: nil context: nil]
和
[UIView commitAnimations]
之间.
代码部分详细介绍相关属性
CALayer基本介绍:
- CALayer负责绘制, 提供UIView需要展示的内容, 不能交互
- UIView负责交互,显示CALayer绘制的内容
- CALayer(层)是屏幕上的一个矩形区域, 在每一个UIView中都包含一个根
- CALayer, 在UIView上的所以视觉效果都是在这个Layer上进行的.
1: 在 iOS 中, 我们能看见的, 例如按钮, 文本, 标签, 输入框, 等等 都是 UIView
2: 其实 UIView 之所以能显示在屏幕上, 完全是因为它内部的一个图层, 在创建 UIView 对象的时候, UIView 内部会自动创建一个图层就是(CALayer 对象), 通过 UIView 的 layer 属性就可以访问这个层
3: 当 UIView 需要显示到屏幕上时, 会调用 drawRect: 方法进行绘图, 并且将所有的绘制内容在自己的图层上绘制, 给图层绘制完毕后, 系统将会拷贝图层到屏幕上, 完成 UIView 的显示
4: UIVIew 本身是不具备显示功能的, 真正拥有显示功能的是里面的 layer 层
5: 通过 UIView 的图层, 可以调整 UIView 的一些界面属性, 例如阴影 圆角 边框 颜色
CALayer外形特征主要包括:
- 层的大小尺寸
- 背景色
- 内容(可以填充图片或者使用Core Graphics绘制的内容)
- 积习是否使用圆角
- 矩形是否有阴影
CALayer常用属性:
与UIView动画相比, CoreAnimation能够实现更多复杂, 好看, 高效的动画效果:
- 阴影, 圆角, 带颜色的边框
-
3D变换
-
透明遮罩
-
多级非线性动画
-
CALayer的坐标系统比UIView多了一个anchorPoint属性
anchorPoint锚点相对自身bounds来说,默认值为(0.5,0.5),即是anchorPoint的默认值在layer的中心点,它的值在0~1之间简单图示锚点
CoreAnimation动画
-
CoreAnimation动画位于iOS框架的Media层
-
CoreAnimation动画实现需要添加QuartzCore.Framework
-
CoreAnimation基本上是Layer Animation
-
CABasicAnimation基本单一类型的动画
-
CAKeyframeAnimation 帧动画, 主要操作属性与keyPath 和 values值组合
-
CAAnimationGroup组合动画, 操作属性: animations将CAAnimation类型的动画加入数组, FIFO队列的方式执行
1: 核心动画的基本概念
① core Animation, 核心动画, 是一组非常强大的动画处理 API, 可以用少量的代码, 实现强大的功能
② core Animation, 可以用在 Mac OS 和 iOS 两个平台
③ core Animation, 动画的执行过程, 都是在后台操作的, 所以不会阻塞主线程
④ core Animation, 是直接操作 CALayer 层的, 并不是 UIView
2: CAAnimation
① 所有动画的父类, 负责控制动画的持续时间和速度, 他是一个抽象的类, 不能直接使用, 应该使用他的子类
② 属性说明:
- duration: 动画的持续时间
- repeatCount: 动画的重复次数
- repeatDuration: 重复时间
- removeOnCompletion (BOOL): 默认为 YES, 表示动画执行完毕后就从图层上移除, 图形会恢复到执行之前的状态. 如果想要保持执行之后的状态, 那就设置 NO, 但是, 还需要设置 fillMode 值为 kCAFillModeForwards
- fillModel: 决定当前对象在非活动的时间段的行为, 比如动画开始前或者动画结束之后 (想要 fillMode 有效, 最好将removeOnCompletion = 0);
- kCAFillModeRemove:
默认值也就是当前动画开始前和动画结束后, 动画对 layer 都没有影响, 动画结束后, layer 会恢复之前的状态
- kCAFillModeForwards:
当前结束动画后, layer 会一直保持最后的状态 - kCAFillModeBackwards:
在动画开始之前, 只需要将动画加入一个 layer, layer 便立即进入动画的初始状态并等待动画的开始. - kCAFillModeBoth: 就是上面两个 kCAFillModeForwards 和kCAFillModeBackwards 的合成
- beginTime: 可以用来设置动画的延迟时间, 若想设置延迟 2秒, 那么就设置 CACurrentMediaTime() + 2 CACurrentMediaTime()图层当前的时间
- timeFuncation: 速度控制函数 控制动画运行的节奏
—> CAMediaTimingFunctionLinear (线性): 匀速, 给你一个相对静态的感觉
—> CAMediaTimingFunctionEaseIn (淡入): 动画缓慢进入, 然后加速离开
—> CAMediaTimingFunctionEaseOut (淡出): 动画全速进入, 然后减速到达目的地
—> CAMediaTimingFunctionEaseInEaseOut (淡入淡出)
③ CAAnimation 的子类
- CABasicAnimation
- CALeyFrameAnimation
- CAAnimationGroup
- CASpringAnimation
④ 属性说明
- keypath: 通过制定 CALayer 的一个属性名称为 keypath(NSString 类型) , 并且对 CALayer 这个属性值进行修改, 达到相应的动画效果, 比如, 制定@\”postion\”为 keypath , 就相当于修改了 CALayer 的 poison 属性的值,达到平移的动画效果.
- 下面的代码部分会对这个 关建路径支持结构字段 进行相应的总结
关键路径支持的部分字段说明
- 关键路径支持的部分字段补充说明
margin = 布局
zPosition = 翻转
backgroundColor = 背景颜色
cornerRadius = 圆角
borderWidth = 边框宽
bounds = 大小
contents = 内容
contentsRect = 内容大小
cornerRadius = 圆角
frame = 大小位置
hidden = 显示隐藏
mask 遮罩
masksToBounds
opacity 不透明的
position 位置
shadowColor 阴影颜色
shadowOffset 阴影偏移量
shadowOpacity 阴影不透明的
shadowRadius 阴影半径
transform.scale = 比例转换
transform.scale.x =以 x轴 比例转换
transform.scale.y = 以 y轴 比例转换
transform.rotation.z = 平面圆形旋转
3: 关键帧动画 与 CABasicAnimation 的区别
① CABasicAnimation只能从一个数值(fromvalue) 变换到另外一个数值 (tovaule)
② 关键帧动画, 会使用一个 NSArray 保存这些数值
4: 动画组
① 属性说明:
- animations: 用来保存一组动画对象NSArray
- 默认情况下, 一组动画对象是同时运动的, 也可以通过设置动画的 beginTime 属性来更改动画的开始时间
5: 转场动画 ——– CATransition: ————–
CATransition: 用于做转场动画效果, 能够为 layer 层提供移出屏幕和移入屏幕的动画效果
① 动画属性:
- type: 动画的过渡效果
类型字符串 效果说明
fade 交叉淡化过渡
push 新视图把旧视图推出去
moveIn 新视图移到旧视图上面
reveal 将旧视图移开,显示下面的新视图
cube 立方体翻转效果
oglFlip 上下左右翻转效果
suckEffect 收缩效果,像一块布被抽走
rippleEffect 水滴效果
pageCurl 向上翻页效果
pageUnCurl 向下翻页效果
cameraIrisHollowOpen 相机镜头打开效果
cameraIrisHollowClose 相机镜头关闭效果
- subtype: 动画的过渡方向
- startProgress: 动画的起点(在整个动画的百分比)
- endProgress: 动画的终点
UIView 的基础动画 代码总结
实例1: 自定义一个属性 MyLabel (UILabel)类型的 展示的是 UIView 的动画效果, 在一个触发方法里面实现动画,我这里写在 TouchBegin 里面.
//1. 创建一个动画[UIView beginAnimations:nil context:nil];//2. 动画延迟设置[UIView setAnimationDelay:1];//3. 给动画添加代理(不遵循代理协议, 也能实现代理方法)[UIView setAnimationDelegate:self];//4. 给动画添加方法(动画结束后执行)[UIView setAnimationDidStopSelector:@selector(stopAc)];//5. 动画持续时间(完成动画所需时间)[UIView setAnimationDuration:2];//6. 设置动画是否会做一次反向的执行 (等会属性里面再说)[UIView setAnimationRepeatAutoreverses:YES];//7. 设置动画移动的新位置self.MyLabel.frame = CGRectMake(100, 100, 100, 100);//8. 开始提交动画 (解释可以看下面)[UIView commitAnimations];
基础动画–**这个 MyLabel 从开始的位置移动到新位置,设置了反向执行 YES 所以到达新位置后又反向移动了最后才来到新位置**
总结一下这里涉及的方法: 均是 UIView 的类方法
- 第 1个方法: 动画马上开始:begin
+(void)beginAnimations:(NSString*)animationID context:(void *)context{}# 参数1: animationID 作为动画的标示使用, 可以方便移除动画操作# 参数2: context 动画的设置 自定义的一些动画数据,这些数据将发送给动画的代理方法 默认 nil
- 最后 1 个方法: commit
# 这个方法 就是提交动画 也是标记动画的内容已经编辑好了 可以使用效果了+ (void)commitAnimations
在这两个方法之间就我们进行,动画相关的一些设置,下面是一些设置的方法
# 设置代理 及其 方法不需要设置遵循代理方法 默认 nil 没有代理+ (void)setAnimationDelegate:(nullable id)delegate;+ (void)setAnimationWillStartSelector:(nullable SEL)selector;+ (void)setAnimationDidStopSelector:(nullable SEL)selector;# 设置动画持续时间 默认 = 0.2+ (void)setAnimationDuration:(NSTimeInterval)duration;# 设置动画的延迟时间 默认是不延迟 就是0.00+ (void)setAnimationDelay:(NSTimeInterval)delay;# 设置动画的开始时间 default = now ([NSDate date])+ (void)setAnimationStartDate:(NSDate *)startDate;# 设置动画的曲线方式(动画的总体变化的时间曲线:开始快最后慢,开始慢最后快,最后慢,均匀线性) 默认default = UIViewAnimationCurveEaseInOut/*typedef NS_ENUM(NSInteger, UIViewAnimationCurve){UIViewAnimationCurveEaseInOut,UIViewAnimationCurveEaseIn,UIViewAnimationCurveEaseOut,UIViewAnimationCurveLinear};*/+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;# 动画的重复次数 default = 0.0.+ (void)setAnimationRepeatCount:(float)repeatCount;# 设置动画是否做一次反向的执行。/*如果设置为YES:动画将执行:动画初始状态->动画->动画完成状态->动画->动画初始状态 。如果设置为NO:默认值*/+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;# 设置动画的开始状态/*YES : 第一个动画正在 执行时候, 另一个动画恰好开始, 这样第一个动画的当前状态, 就是另一个动画的开始状态NO: 第一个达到完成状态, 下一个动画才开始执行动画的效果*/+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;# 设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好/*UIView官方提供五种动画效果供大家使用,分别为:UIViewAnimationTransitionNone 不使用动画UIViewAnimationTransitionFlipFromLeft 从左向右旋转翻页UIViewAnimationTransitionFlipFromRight 从右向左旋转翻页UIViewAnimationTransitionCurlUp 卷曲翻页,从下往上UIViewAnimationTransitionCurlDown 卷曲翻页,从上往下*/+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;# 设置view是否有动画效果/*YES: 默认有动画的能力NO: 关闭动画效果效果关闭并不会对 UI 的改变有什么影响只是不会 \"动画\" 了而已, 其他的大小什么属性依然有效的*/+ (void)setAnimationsEnabled:(BOOL)enabled;# 判断当前的动画效果是否关闭了+ (BOOL)areAnimationsEnabled;
通过 UIView 的几个 Block 方法进行动画设置
- // 实现动画 的 Block1
参数1 : Duration 动画持续时间 Block 里面就写你要实现的效果(位置的改变等)
[UIView animateWithDuration:2 animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
}];
- // 实现动画 的 Block2```code# 参数比上面多一个 动画结束后的操作[UIView animateWithDuration:2 animations:^{self.MyLabel.frame = CGRectMake(100, 100, 200, 200);} completion:^(BOOL finished) {NSLog(@\"动画结束的操作可以写这里\");}];```- // 实现动画 的 Block3```code/*参数1: Duration: 动画持续时间参数2: delay: 延迟时间参数3: options: 枚举值 动画的效果类型*/[UIView animateWithDuration:2 delay:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{self.MyLabel.frame = CGRectMake(100, 100, 100, 100);} completion:^(BOOL finished) {NSLog(@\"结束了%d\", finished);}];```- //实现动画的Block4 弹簧效果```code/*Spring: 模拟弹簧弹跳的效果参数: Damping:阻尼 0-1 阻尼越小动画越明显参数: initialSpringVelocity : 动画初始变化速度参数: options 转变的风格 枚举值*/[UIView animateWithDuration:10 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:15 options:(UIViewAnimationOptionCurveEaseInOut) animations:^{self.MyLabel.center = CGPointMake(self.view.center.x, 100);} completion:^(BOOL finished) {NSLog(@\"弹簧效果结束\");}];```- //实现动画的Block5 关键帧动画 也就是里面有好几个动画进行转变```code/*Duration:持续时间delay: 延迟时间options: 枚举值 动画的风格*/[UIView animateKeyframesWithDuration:3 delay:0 options:(UIViewKeyframeAnimationOptionRepeat) animations:^{/*参数1: RelativeStartTime: 相对的开始时间参数2: relativeDuration:相对持续时间*/[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{self.MyLabel.center = self.view.center;}];[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.3 animations:^{self.MyLabel.frame = CGRectMake(100, 100, 100, 100);}];[UIView addKeyframeWithRelativeStartTime:0.8 relativeDuration:0.3 animations:^{self.MyLabel.frame = CGRectMake(100, 400, 100, 100);}];} completion:^(BOOL finished) {NSLog(@\"结束了\");}];
- CAAnimation 的子类
———— CABasicAnimation —————–
# 1: 创建 以字段为 旋转变换CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@\"transform.rotation\"];# 动画效果的初始值basic.fromValue = @0;# 动画效果变化的结束值 (绝对值) 这里就是旋转的角度从多少转到多少度basic.toValue = @(2*M_PI);# 动画执行时间basic.duration = 5;# Layer 动画需要天加到 layer 上 forkey 我们可以写上我们标记的动画属性[self.MyLabel.layer addAnimation:basic forKey:@\"transform.rotation\"];
这个效果就是旋转360°(顺时针–>初始值比结束值小),
——— CAKeyFramAnimation 关键帧动画——–
// 创建 以关键字段 位置变化CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@\"position\"];// 建几个动画的位置CGPoint p1 = CGPointMake(0, 0);CGPoint p2 = CGPointMake(0, 400);CGPoint p3 = CGPointMake(400, 100);CGPoint p4 = CGPointMake(100, 200);CGPoint p5 = CGPointMake(200, 300);NSValue *v1 = [NSValue valueWithCGPoint:p1];NSValue *v2 = [NSValue valueWithCGPoint:p2];NSValue *v3 = [NSValue valueWithCGPoint:p3];NSValue *v4 = [NSValue valueWithCGPoint:p4];NSValue *v5 = [NSValue valueWithCGPoint:p5];//属性 values : 数组对象 里面的元素称为\"keyFrame\"(关键帧), 动画对象会在指定的时间里 (duration). 依次显示values 数组中的每一个关键帧keyframe.values = @[v1,v2,v3,v4,v5];keyframe.duration = 10;// 每一帧的时间, 每一帧的时间为比例的累加计算 取值范围 0-1,没有设置的话 每一帧的时间是平分的keyframe.keyTimes = @[@0.1,@0.1,@0.1,@0.1];[self.MyLabel.layer addAnimation:keyframe forKey:@\"系统保留关键字\"];
关键帧动画的演示
——— CAAnimationGroup 动画组——–
// 创建CAAnimationGroup *group = [CAAnimationGroup animation];group.duration = 10;// 把上面两个动画加到这个动画组里面group.animations = @[basic,keyframe];[self.MyLabel.layer addAnimation:group forKey:@\"同上\"];
————— CASpringAnimation 模拟弹簧动画效果——–
// 创建一个弹簧动画 结构关键字段 意思是竖直方向上 模拟弹簧CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@\"position.y\"];// 设置动画效果的初始值spring.fromValue = @50;// 设置动画的结束值spring.toValue = @10;// 阻尼系数spring.damping = 0.1;// 刚度系数: (劲度系数 / 弹性系数): 系数越大,形变的产生的力越大, 运动越快spring.stiffness = 10;// 质量: 影响图层运动时候的惯性, 质量越大弹簧拉伸和压缩的幅度越大 (动画的幅度,波动变大)spring.mass = 1;// 初识速率: 动画视图的初识速度大小// 速率为正时候, 速度方向与运动方向一致, 否则相仿.spring.initialVelocity = 1;// settlingDuration 结算时间,预估弹簧动画到停住的时间的估算, 根据当前动画的各个参数估算, 通常弹簧动画的估算时间使用结算时间比较准确spring.duration = spring.settlingDuration;[self.MyLabel.layer addAnimation:spring forKey:@\"弹簧\"];
弹簧效果动画
———- CATransition ——-
// 创建CATransition *trans = [CATransition animation];// 效果trans.type = @\"pageCurl\";// 开始位置 (0-1)trans.startProgress = 0;// 结束位置 (0-1)trans.endProgress = 1;// 效果方向trans.subtype = kCATransitionFromLeft;// 重复次数trans.repeatCount = 10;// 持续时间trans.duration = 3;[self.MyView.layer addAnimation:trans forKey:@\"11\"];
转场动画效果图
实例: 切换图片参考;