核心动画
- 核心动画
当修改一个 CALayer 的属性时,它会通过-actionForKey:
来查询属性对应的 action,而 key 就是对应的属性名称。
CAAnimation 遵守 CAAction
协议,返回的 action 其实就是一个 CAAnimation 动画对象。
一般默认返回的是 CABasicAnimation,默认动画时间0.25秒,动画速率函数为渐入渐出效果(kCAMediaTimingFunctionEaseInEaseOut)。
View 和 Layer 的关系:
所有的 View 都是由一个底层的 Layer 来驱动的,View 只是一个简单的控制器,View 的绝大多数属性都是从 Layer 对象中获取的数据。
而
AVCaptureVideoPreviewLayer
和CAShapeLayer
是不需要附加到 View 上就可以在屏幕上显示内容。
Layer 的自定义动画
可以通过监听自定义 Layer 的自定义属性值的变动,实现自定义动画。
-
监听自定义属性的 setter 方法,实现对应动画。
-
利用自定义属性的
dynamic
特性自行实现属性的 ivar 和 getter 方法,进行监听值的变化。通过重写
+needsDisplayForKey:
方法可以监听属性值的变化。自定义属性必须是可进行插值(interpolate)的,否则无法获取属性的增量值。
+ (BOOL)needsDisplayForKey:(NSString *)key { // time 属性修改 if ([@"time" isEqualToString:key]) { // layer 的 display 函数会调用 return YES; } return [super needsDisplayForKey:key]; } - (void)display { // 使用 presentation Layer 来获取当前属性值 // 而 model Layer 表示的是实际设置的属性最终值 NSLog(@"time: %f", [[self presentationLayer] time]); // 使用 Core Graphics 函数绘制动画 } // 当属性 time 变化时,添加新的动画 - (id<CAAction>)actionForKey:(NSString *)key { if ([key isEqualToString:@"time"]) { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key]; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; animation.fromValue = @([[self presentationLayer] time]); return animation; } return [super actionForKey:key]; }
model Layer(模型层)和 presentation Layer(表示层)的区别:
- 前者负责数据的存储和获取。表示正在进行的动画结束时 layer 所达到的最终状态。
- 后者负责效果的展示,是前者的一个拷贝,表示的是当前的中间动画状态。
属性赋值时修改的是 model Layer 中的值,下次屏幕刷新时 presentation Layer 的状态会回到 model Layer 的状态。
Layer 自带的仿射动画
CGAffineTransform 形变就是把二维形变使用一个三维矩阵来表示,其中第三列总是(0,0,1),形变通过矩阵前两列来控制。
系统提供了 CGAffineTransformMake 结构体来控制形变。
动画函数 | 意义 |
---|---|
CGAffineTransformIdentity | layer 形变动画的还原(单位矩阵) |
CGAffineTransformMakeTranslation | 平移动画(tx,ty) |
CGAffineTransformMakeScale | 缩放动画(sx,sy) |
CGAffineTransformMakeRotation | 旋转动画(angle) |
CGAffineTransformTranslate | 实现在已存在的形变动画上的平移动画(t,tx,ty) |
CGAffineTransformScale | 实现在已存在的形变动画上的缩放动画(t,sx,sy) |
CGAffineTransformRotate | 实现在已存在的形变动画上的旋转动画(t,angle) |
CGAffineTransformInvert | 实现形变动画的翻转效果(t) |
CGAffineTransform _ Apple Developer Documentation
iOS CoreAnimation专题——实战篇(四)基于拖动手势的视图3D旋转效果 - CSDN博客
iOS 动画分为显式动画和隐式动画。
UIView 隐式动画
当我们修改界面的 CALayer 的可动画属性时,就会触发系统的隐式动画。
但是,系统中默认 UIView 对应的 CALayer 关闭了隐式动画。所以直接做出修改时无法产生效果的。
UIView 有一系列的 animatedWithDuration
动画,可以使用 animation block 重新开启默认关闭的 Layer 动画。
当属性在动画 block 中被改变时,就附加了动画效果。
属性改变时 Layer 会向 View 请求一个动作,而一般情况下 View 将返回一个 NSNull。
只有当属性改变发生在动画 block 中时,系统会通过addAnimation:forKey:
方法将动画添加到 Layer中, View 才会返回实际的动作。
显式动画
关键帧动画:最少含有起始帧、结束帧,中间的过渡效果由系统自动生成。
逐帧动画:周期性的调用绘制方法,绘制每帧的动画对象。比如,重写 UIView 的 - drawRect:
方法来修改视图属性绘制视图。
iOS 的动画都是基于 CALayer 的,使用 CADisplayLink(基于屏幕刷新的,每次屏幕刷新都会触发调用)来周期性调用指定方法。
调用
addAnimation:forKey:
方法时,要注意设置 key 值。设置 key 值后,系统再次执行该动画时会先检查该动画是否被创建。查找成功后会开头执行,失败后创建动画。
CAPropertyAnimation
当对属性赋值时,layer 会让它的 delegate 调用actionForLayer:forKey:
方法获取一个返回值:
- 返回值可能为 nil,则 layer 会走自己的隐式动画。
- 返回值可能是 NSNull,则 layer 不会做任何动画。
- 返回值是一个实现了 CAAction 协议的对象,则 layer 会用该对象生成一个 CABaseAnimation 加到自身并执行动画。
CABasicAnimation
基本动画通过设置起始帧、结束帧的信息来实现动画效果。
属性 | 解释 |
---|---|
duration | 动画的持续时间 |
repeatCount | 动画持续次数(可以设置小数值,默认值为 0) |
repeatDuration | 在设置的时间内,动画一直执行不计次数 |
beginTime | 指定动画开始的时间 |
timingFunction | 设置动画的速度变化 |
fillMode | 动画在开始和结束时的动作,默认值是 kCAFillModeRemoved |
autoreverses | 动画结束时是否执行逆动画 |
fromValue | 所改变属性的起始值 |
toValue | 所改变属性的结束值 |
byValue | 所改变属性相同起始值的改变量 |
additive | 使 Core Animation 在更新 presentation layer 之前将动画的值添加到 model layer 中去。 对于所有形式的需要更新的元素可以重用相同的动画,且无需提前知道它们的位置。 默认值为 NO。 |
removedOnCompletion | 动画完成后其是否从渲染树中移除。默认值为 YES。 |
repeatCount
想要设置一直不断重复时,在 Swift 中使用Float.infinity
,OC 中使用HUGE_VALF
。
timingFunction
用来设置时间段内动画的速度变化。可以使用 CAMediaTimingFunction 的 +functionWithControlPoints::::
函数自定义速率函数。
使用 CAKeyFrameAnimation 时,可以使用 timingFunctions 来指定阶段性的速度变化函数。
-
kCAMediaTimingFunctionLinear
在整个动画时间内动画都是以一个相同的速度来改变,即匀速运动。此值为 timingFunction 的默认值。
-
kCAMediaTimingFunctionEaseIn
动画开始时较慢,之后动画会加速。
-
kCAMediaTimingFunctionEaseOut
动画在开始时会较快,之后动画速度减慢。
-
kCAMediaTimingFunctionEaseInEaseOut
动画在开始和结束时速度较慢,中间时间段内速度较快。
-
kCAMediaTimingFunctionDefault
它和 kCAMediaTimingFunctionEaseInEaseOut 很类似,但是加速和减速的过程都稍微有些慢。
fillMode
-
kCAFillModeForwards
动画开始之后 layer 的状态将保持在动画的最后一帧。
可以用来表示动画变换后 layer 保持为最终状态(需要配合设置
removedOnCompletion = NO
)。
当设置属性removedOnCompletion = YES
时,此值无效。 -
kCAFillModeBackwards
设置此值后将会立即执行动画的第一帧。
设置此值会忽略 beginTime 属性。
-
kCAFillModeBoth
该值是 kCAFillModeForwards 和 kCAFillModeBackwards 的组合状态。
-
kCAFillModeRemoved
动画将在设置的 beginTime 开始执行,动画执行完成后会将 layer 的改变恢复原状。
delegate
animationDidStart:
:动画开始animationDidStop:finished
:动画结束
常见的 keyPath
CALayer 的 Animatable 属性直接赋值可以产生隐式动画,可以在 CAAnimation 的 keyPath 中设置。
keyPath值 | 说明 |
---|---|
transform.scale transform.rotation transform.translation |
比例缩放 旋转状态 平移状态(具体方法同下) |
transform.scale.x transform.scale.y |
缩放宽/高的比例 |
transform.rotation.x transform.rotation.y transform.rotation.z |
围绕x/y/z轴旋转 |
backgroundColor | 背景颜色的变化 |
bounds | 大小缩放,中心不变 |
position | 位置(中心点改变) |
contents | 内容变化(比如 UIImageView 的变化) |
opacity | 透明度 |
contentsRect.size.width contentsRect.size.height |
横向/纵向拉伸缩放 |
shadowColor | 阴影的颜色 |
shadowOffset | 阴影的偏移 |
shadowOpacity | 阴影的不透明度 |
shadowRadius | 阴影渲染的模糊半径 |
cornerRadius | 绘制圆角时使用的半径 |
borderWidth | 边框的宽度 |
hidden | 隐藏过渡动画 |
CASpringAnimation
它继承于 CABaseAnimation
,用于制作弹簧动画。
- mass:质量,影响图层运动时弹簧惯性。质量越大,弹簧拉伸和压缩的幅度越大,动画的速度变慢,且波动幅度变大。
- stiffness:刚度系数(劲度系数/弹性系数),该系数越大,形变产生的力越大,运动越快。
- damping:阻尼系数,组织弹簧伸缩的系数,阻尼系数越大,停止越快。
- initialVelocity:初始化速率。速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反。
- settlingDuration:结算时间(只读),返回弹簧动画到停止时的估算时间。
该动画只在 iOS 9及其以后可用。
CAKeyframeAnimation
关键帧动画,关键帧动画
就是在动画控制过程中开发者指定主要的动画状态,至于各种状态间动画如何进行则由系统自动运算补充(每个两个关键帧之间系统形成的动画成为补间动画
)。
常见的设置模式:
- 设置不同的属性进行关键帧控制
- 绘制路径进行关键帧控制(优先级高于前者)
CABasicAnimation 只能从一个数值(fromValue)变到另一个数值(toValue),
而 CAKeyframeAnimation 可以使用数组保存一组数值。
CABasicAnimation 可以看做是最多只有2个关键帧的 CAKeyframeAnimation。
属性 | 解释 |
---|---|
values | 由许多关键帧 值组成的数组用来进行动画。(只有在 path 属性为 nil 时才有效) |
path | 可以指定一个路径(CGPathRef/CGMutablePathRef),让动画沿着这个路径执行。 |
cacluationMode | 主要是指对平面中多个离散点的计算模式。 |
keyTimes | 一个包含若干 NSNumber 对象值的数组,用来指定对应的关键帧对应的时间点。 (NSNumber 的值在 0.0~1.0 之间,且后边的值要比前一个大或相等。 此值未设置时,各个关键帧的时间是平分的。) |
timingFunctions | 设置动画的速度变化数组,类似于 values。 |
rotationMode | 设置旋转样式 |
duration | 动画在指定时间内完成 |
cacluationMode
设置平面中多个点的散列方式。
-
kCAAnimationLinear
calculationMode 的默认值。
可以配合 keyTimes 属性自定义线性时间来控制动画的效果(表示关键帧之间以线性进行差值计算)。
-
kCAAnimationDiscrete
表示离散的,不进行差值计算,所有的关键帧直接逐个进行展示。
-
kCAAnimationPaced
向对象添加一个恒定的速度,不论各个阶段线段有多长。设置此属性将忽略 keyTimes 属性。
-
kCAAnimationCubic
平滑执行。对于位置变动的关键帧动画运行更加平滑。
-
kCAAnimationCubicPaced
平滑均匀地执行。
rotationMode
-
kCAAnimationRotateAuto
根据路径自动旋转。
-
kCAAnimationRotateAutoReverse
根据路径自动翻转。
沿路径的动画
通过设置 path 属性代替 values 属性,设置动画。
CGPathRef 和 CGMutablePathRef 都是 CGPath 结构体类型的指针,前者是 const 类型不可修改,后者是可修改的。
创建 CGMutablePathRef 对象时,记得调用 CGPathRelease 方法释放。
常见的创建 Path 的方法:
-
UIGraphicsGetCurrentContext():获取当前绘图上下文
-
CGContextAddPath:将路径添加到绘图上下文中(绘图上下文,路径)
-
CGContextDrawPath:进行绘制(绘图上下文,绘制模式)
-
CGPathMoveToPoint:移动到某点(path,transform 变换,x,y)
-
CGPathAddLineToPoint:从当前点到目标点画线(path,transform 变换,x,y)
-
CGPathCreateMutable():创建可变 path 类
-
CGPathCreateWithRect:创建矩形路径(位置,transform 变换)
-
CGPathCreateWithRounderRect:创建矩形路径(位置,横向圆角,纵向圆角,transform 变换)
-
CGPathCreateWithEllipseInRect:创建椭圆形路径(位置,transform 变换)
-
CGPathCreateCopyByDashingPath:创建虚线路径(进行虚拟化的路径,transform 变换,从第几部分开始绘制虚线,风格数组,数组长度)
CGFloat floats[] = {10,5}; CGPathCreateCopyByDashingPath(pathRef, nil, 0, floats, 2);
-
CGPathAddEllipseInRect:椭圆形动画
椭圆形动画(从右侧开始(0度)顺时针一周回到右侧)
-
CGPathCreateWithEllipseInRect:圆形动画
-
CGPathAddRect:矩形动画
矩形动画(从左上角开始,顺时针运行一周回到最上角)
-
UIBezierPath
- bezierPathWithRect:创建一个矩形
- bezierPathWithRect:cornerRadius:创建一个圆角矩形
- bezierPathWithOvalInRect:创建一个矩形内切圆(椭圆)
- bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise:画圆/圆弧(clockwise:是否顺时针,角度 0 表示圆的最右边那个点)
- moveToPoint:
- addQuadCurveToPoint:controlPoint:
- addQuadCurveToPoint:controlPoint1:controlPoint2:
CATransition
主要用于转场动画,即从一个场景以动画的形式过渡到另一个场景。
-
type:转场动画类型。
API 效果说明 是否支持方向 kCATransitionFade 淡入效果 是 kCATransitionMoveIn 新视图移动到旧视图上 是 kCATransitionPush 新视图推出旧视图 是 kCATransitionReveal 移开旧视图显示新视图 是 kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom从右侧转场
从左侧转场
从顶部转场
从底部转场 -
subtype:转场动画将要去往的方向。
-
startProgress/endProgress:开始和结束的位置进度,数值介于 0~1 之间,且结束值一定大于开始值。
UIView Animation
UIView(UIViewAnimation)
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
+ (void)commitAnimations;
// 设置动画曲线
// UIViewAnimationCurveEaseInOut(默认值)
// UIViewAnimationCurveEaseIn
// UIViewAnimationCurveEaseOut
// UIViewAnimationCurveLinear
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
// 设置过渡动画类型
// UIViewAnimationTransitionNone
// UIViewAnimationTransitionFlipFromLeft
// UIViewAnimationTransitionFlipFromRight
// UIViewAnimationTransitionCurlUp
// UIViewAnimationTransitionCurlDown
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
UIView(UIViewAnimationWithBlocks)
为什么 UIView 的属性动画要设置在 block 内?
CALayer 中存在一个持有者 UIView 的 delegate。
当给 UIView 属性赋值时,除了调用其持有的 CALayer 对应的属性的 setter 方法外,CALayer 还会让其 delegate(即 UIView)调用actionForLayer:forKey:
方法。
当在 block 外 设置属性时,此方法会返回 NSNull。
当在 block 内 设置属性时,此方法会返回正确的 CAAction。
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
// 默认delay为0,options为0
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
// 默认delay为0,options为0,completion为NULL
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;
// 阻尼动画
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
/*
* 转场动画
* 用于实现不能使用属性动画实现的动画效果
* UIViewAnimationOptions:通过控制参数实现不同的动画效果
*/
// 单视图的转场动画需要在动画块中设置视图转场前的内容和视图转场后的内容
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
// 增加toView至fromView.SuperView,从父视图移除fromView
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion;
UIView (UIViewKeyframeAnimations)
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations;
CAAnimationGroup
通过同时为多个属性添加动画来完成一些复杂的效果。
- 可以同时对视图的多个属性做出动画
- 可以将所有的动画作为一个对象暴露出去
- 可以同时控制动画组中的所有动画执行时间
Facebook_pop(An extensible iOS and OS X animation library, useful for physics-based interactions)
扩展阅读
CALayer
CALayer 所共有的特点:可动画属性、隐式动画、transform 变形等。
类型 | 含义 |
---|---|
CAShapeLayer | 根据路径绘制矢量图形 |
CATextLayer | 绘制文字信息 |
CAGradientLayer | 绘制线性渐变色 |
CAEmitterLayer | 各种炫酷的粒子效果 |
CATransformLayer | 使用单独的图层创建 3D 图形 |
CATiledLayer | 将大图裁剪成多个小图以提高内存和性能 |
CAScrollLayer | 没有交互效果的滚动图层,没有滚动边界,可以任意滚动上面的图层内容 |
CAReplicatorLayer | 高效地创建多个相似的图层并施加相似的效果或动画 |
CAEAGLLayer | 用来显示任意的 OpenGL 图形 |
AVPlayerLayer | 用来播放视频 |
anchorPoint 和 position 的关系
-
position
是子图层的anchorPoint
在父视图中的位置。anchorPoint
和position
共同决定图层相对父图层的位置,即frame
的x
,y
。// origin 点的计算 // anchorPoint 值默认为 (0.5, 0.5) frame.origin.x = position.x - anchorPoint.x * bounds.size.width; frame.origin.y = position.y - anchorPoint.y * bounds.size.height;
anchorPoint 是相对于自身的位置,而 position 是相对于父图层的位置。
-
在图层旋转时的固定点。默认坐标点位置为:(0.5, 0.5)。
参考资料:
CAShapeLayer
CAShapeLayer 是一个通过矢量图形而不是 bitmap(位图)来绘制的 CALayer 子类。使用 CAShapeLayer 绘制路径有以下一些优点:
- 渲染速度快。CAShapeLayer 使用了硬件加速,绘制图形比 Core Graphics 快很多。
- 内存使用高效。CAShapeLayer 不需要创建寄宿图形(backing image),所以不会占用很大内存。
- 不会被图层边界裁剪掉。CAShapeLayer 可以在边界外绘制,图层路径不会像使用 Core Graphics 的普通 CALayer 对象被裁剪掉。
- 不会出现像素化。CAShapeLayer 做 3D 变换时,不会像其他有寄宿图形(backing image)的图层变得像素化。
矢量图和位图:
位图:位图是通过排列像素点来构造的,像素点信息包括颜色(RGB) + 透明度(A)。常见的位图有 32 位位图和 24 位位图(不含 Alpha 通道)。
位图在变形时会重新绘制每个像素点的信息,会造成图形的模糊。
通过将复杂的绘制内容转换为位图数据,然后再由 GPU 渲染可以大幅提高位图的绘制效率。
矢量图:矢量图是对多个点进行布局,然后按照一定规则进行连线后形成的图形。矢量图的信息主要有点属性(包括点的坐标、连线顺序等)和线属性(包括线宽、描线颜色等)。
矢量图在形变过程中,只会将点进行重新布局,然后按照点属性和线属性进行连线。
CAShapeLayer 中几个常见的 Animatable 的属性:
-
fillColor:填充颜色
-
strokeColor:描线颜色
-
strokeStart:表示描线开始的位置
-
strokeEnd:表示描线结束的位置
-
path:路径
// fromPath 和 toPath 是两段不同的曲线 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; animation.duration = 5; animation.fromValue = (__bridge id _Nullable)(fromPath.CGPath); //animation.toValue = (__bridge id _Nullable)(toPath.CGPath); // 直接修改 modelLayer 来替代 toValue shapeLayer.path = toPath.CGPath; [shapeLayer addAnimation:animation forKey:nil];
Animating the Drawing of a CGPath With CAShapeLayer – Ole Begemann
CAShapeLayer 与 mask 的结合使用:
mask 蒙版的常见实现方式有:使用图片做蒙版、使用 CAShapeLayer 绘制图形做蒙版。
mask 蒙版上还可以添加自定义动画效果。
// 使用图片作为蒙版
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(self.imageView.centerX /8.0f, self.imageView.centerY /7.f, self.imageView.width /1.5f, self.imageView.height /1.5f);
layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"first"].CGImage);
self.imageView.layer.mask = layer;
// 使用 CAShapeLayer 绘制图形作为蒙版
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = path.CGPath;
maskLayer.lineWidth = 10.0f;
// 填充颜色为透明时,填充内容不再作为蒙版内容
maskLayer.fillColor = [UIColor clearColor].CGColor;
// 不设置为透明色时,描线颜色就会作为蒙版内容
maskLayer.strokeColor = [UIColor redColor].CGColor;
self.imageView.layer.mask = maskLayer;
// 为蒙版添加动画效果
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 3.0f;
animation.fromValue = @0;
[maskLayer addAnimation:animation forKey:nil];
iOS CoreAnimation专题——技巧篇(三)Layer Masking - 图层蒙版 - CSDN博客
CAGradientLayer
CAGradientLayer 可以实现线性渐变的效果,coreGraphics 可以绘制出更多渐变效果(实现复杂)。
- colors:设置渐变颜色的数组
- startPoint、endPoint:表示渐变的方向、渐变开始的地方和渐变结束的地方。
- locations:渐变颜色所占比例。
将 CAGradientLayer 渐变效果与 mask 蒙版结合能够实现复杂的渐变效果,
将 Animation 动画加到 mask 蒙版上更能够实现复杂的渐变动画。
iOS CoreAnimation专题——实战篇(一)惊艳的进度条效果实现 - CSDN博客
CAMediaTiming 协议
-
repeatCount:动画重复次数,设置为
HUGE_VALF
时表示无限重复。 -
repeatDuration:动画总时长,如果大于单次时长则动画重复。
-
beginTime:开始时间。
设置为 CACurrentMediaTime() +/- x 时:
当为 + 时,延迟执行 x 秒。
当为 - 时,直接执行 x 秒后的动画。 -
duration:单次动画时长。
-
speed:图层相对于父图层的速度,默认为1。
-
timeOffset:时间偏移量。
设置偏移量时,动画会从绝对时间偏移相应的时间执行动画。比如:
动画执行顺序为:1 => 2 => 3 => 4 => 5
timeOffset 为2后的执行顺序为:3 => 4 => 5 => 1 => 2
timeOffset 为4后的执行顺序为:5 => 1 => 2 => 3 => 4// speed 和 timeOffset 的配合使用可以用来控制动画的时间轴 - (void)animationForColorViewBackgroundColor { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; animation.fromValue = (__bridge id _Nullable)([UIColor orangeColor].CGColor); animation.toValue = (__bridge id _Nullable)([UIColor blueColor].CGColor); animation.duration = 1.0f; [self.colorView.layer addAnimation:animation forKey:@"backgroundColor"]; // 暂时停止动画 self.colorView.layer.speed = 0.0; } // 根据 slider 的值控制背景色渐变效果 - (IBAction)sliderValueChanged:(UISlider *)sender { NSLog(@"current slider value:%.2f",sender.value); // 设置动画时间轴偏移量 self.colorView.layer.timeOffset = sender.value; }
-
repeatDuration:重复的时间间隔,优先级大于repeatCount。
-
autoreverses:是否自动翻转动画。
-
fillMode:动画在开始和结束时的动作。
动画的暂停和恢复:
// 暂停动画
- (void)pauseLayer:(CALayer *)layer {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
// 恢复动画
- (void)resumeLayer:(CALayer *)layer {
CFTimeInterval pausedTime = layer.timeOffset;
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Controlling Animation Timing(控制动画时机)
CADisplayLink
FPS(frame per second):帧率,也就是屏幕每秒钟刷新次数。如果帧率为60,表示屏幕每秒刷新60次,但是并不是每次屏幕刷新的时间间隔都是平均的。
CADisplayLink:就是屏幕保持 >60 fps 的帧率进行刷新,每次刷新都会根据绘制信息重绘屏幕上的显示内容。
// 创建 CADisplayLink 对象
+ (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel;
- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode;
- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode;
// 停止刷新
- (void)invalidate;
// 可以通过属性的设置来控制屏幕刷新的暂停与开始
@property(getter=isPaused, nonatomic) BOOL paused;
系统默认提供了两个常用的runloop mode:NSDefaultRunloopMode 和 NSRunLoopCommonModes。
一个 runloop只能在某个 mode 中运行,runloop 可以在多个不同 mode 间进行切换。
iOS CoreAnimation专题——实战篇(三)CADisplayLink高级应用:让视图的四条边振动起来 - CSDN博客
CAMediaTimingFunction
常见的 timingFunction:
- kCAMediaTimingFunctionLinear
- kCAMediaTimingFunctionEaseIn
- kCAMediaTimingFunctionEaseOut
- kCAMediaTimingFunctionEaseInEaseOut
- kCAMediaTimingFunctionDefault
// 创建自定义的动画速率变化函数
+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
参考资料
- Core Animation 编程指南(官方)
- iOS动画详解(学习动画看这一篇就够了) - CocoaChina_让移动开发更简单
- iOS CoreAnimation专题——总览篇 - CSDN博客
- iOS 动画分享(关键帧动画和波浪动画) - CocoaChina_让移动开发更简单
- 动画黄金搭档 CADisplayLink & CAShapeLayer - CocoaChina_让移动开发更简单
- iOS 核心动画高级技巧
- iOS 保持界面流畅的技巧 - Garan no dou