快捷搜索:

Core Animation 学习笔记2 - Layer

包孕 CABasicAnimation 的一些简单动画,Spring 后面的再学。

近来开始忙项目了,停较长一段光阴

6. Layer

Layer 概述

Layer 是一个简单的工具,只对外供给一些图像显示方面的内容相关的属性,每一个 UIView 背后都有一个 Layer 层。

Layer 跟 UIView 是不一样的,主要由于:

Layer 只是一个简单的模型工具,不像 UIView 那么逻辑工具,没有繁杂的自动结构和手势识别等。

Layer 预定义了很多可见的特点,这些特点是一系列的出现在屏幕上的内容的数据,比如界限线、边框颜色、位置、阴影等。

Core Animation 优化了对 layer 的支持,比如缓存,并且直接应用 GPU 进行绘制。

UIView 之以是繁杂,是由于他还认真了 NSAutoLayout 用户交互等繁杂的逻辑,然则Layer没有任何逻辑,只是供给了缓存和 GPU 绘制。

以是 UIView 异常机动灵便,有很多的子类,然则 Layer 子类就异常少,层级加倍简单。

UIView 任何时刻都能胜任事情,然则假如要斟酌优化和机能的时刻就得斟酌 Layer 了。

Core Animation 操作 Layer 同样跟 UIView 一样经由过程设定起终点的状态以及过度要领来操作,只是在 Layer 中不仅仅可以操作之前的:frame、position、opacity,还有更多属性可以改动。

6.1 Layer 属性

定位与尺寸 position size

bounds : 改变layer的界限frame

positon : 可以理解成 UIView 的 center,具有 x y 两个属性。

transform : Layer 的 transform 还可以 3D 变换,改动 scala, 角度 rotate .

界限 border

borderColor : tint 界限颜色

borderWidth : 界限宽度

borderRadius : 圆角矩形圆角半径

阴影 shadow

shadowOffset: 代表阴影跟Layer的偏移

shadowOpacity: 改动这个值让阴影渐进渐出

shadowPath: 改动 Layer 的阴影的外形

shadowRadius:让阴影变隐隐

内容 Contents

着末这些属性节制末了了给 Layer 展示的数据,直接用户看到的一层

contents: 改动这个值去分配原生的 TIFF 或 PNG 数据给 Layer 的内容

mask: 改动这个值去重修外形跟图像。

opacity: 透明度

UIView 的动画不能指定开始状态,然则 Layer 很多环境下可以指定开始状态。

6.2 CABasicAnimation

创建一个 CABasicAnimation 工具:

然后创建一个 CABasicAnimation 工具,然后添加到 view 的 layer 上,keyPath 用来指定动画的属性,上面提到过的属性都可以作为动画目标属性。

let flyRight = CABasicAnimation(keyPath: "position.x")

flyRight.fromValue = -view.bounds.size.width/2

flyRight.toValue = view.bounds.size.width/2

flyRight.duration = 0.5

//把动画添加到 layer 上

heading.layer.add(flyRight, forKey: nil)

当我们这样创建一个 CABasicAnimation 的时刻,flyRight 只是一个工具,它跟任何一个 layer 都没有关系。当 add 措施调用的时刻,传入绑定 Layer 的是一个它的 copy,并不是我们创建的这个工具本身。

以是我们可以复用 CABasicAnimation 工具。

fillMode 动画模式

应用动画工具的这个属性,让你节制动画在开始到停止的全部流程呈现的状态。

关于 Layer 动画状态的节制,经由过程 fillMode 变量来节制 layer 肇端状态的展示。

用动画开始和停止来瓜分一个 Layer 的光阴线,可以分为三个区域,动画开始前,动画中,以及动画停止后,fillMode 的四个值,包括了动画的四种前后帧的留存环境。

经由过程设置 动画的 fillMode 属性,可以节制动画帧在动画开始之前以及停止之后的停顿与否的影响,有四个罗列值:

kCAFillModeRemoved: 仅动画时代

kCAFillModeBackwards: 以及开始之前

kCAFillModeForwards: 以及停止之后

kCAFillModeBoth: 包括开始停止

以是当你改变了动画的开始停止光阴,应该斟酌到 presentation layer 层的留存环境。

比如延迟动画光阴:

flyRight.beginTime = CACurrentMediaTime() + 0.3

flyRight.fillMode = kCAFillModeBoth

另一个属性是 isRemovedOnCompletion,这个属性默认值为 true,停止的时刻假如要保留 Layer 位置,就要设置为 false。

动画层 与 Layer 层

当履行动画的时刻,我们看到的不是真正的 Layer,而是一个 presentation layer,动画履行完毕,展示的 Layer 就会移出视图,然后从新展示原始的 Layer。

展示 Layer 也不接管交互事故的。

CABasicAnimation 有一个属性 isRemoveOnCompletion,这个属性结合上一个 fillMode,设置前者为 false,后者为kCAFillModeBoth,可以在动画停止的时刻,把动画着末的一个 Layer 留存下来。

然则只管即便避免保留动画的 Layer 层,斟酌机能以及手势的问题,当一个动画运行完毕,就移出界面,然后更新 UIView 的属性。

6.2 动画 Keys & Delegate

CAAnimationDelegate

UIKit API 的 UIView 动画只能根据 Closure 进行动画,一旦开始,不能停息竣事或者获取动画工具。

比拟之下 CA 动画的灵便性就对照强,有获取动画工具、设置代理措施。

CAAnimation 跟 CABasicAnimation 都遵守了代理 CAAnimationDelegate,开始停止的代理措施如下:

extension ViewController: CAAnimationDelegate {

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {

print("animation did finish.")

}

func animationDidStart(_ anim: CAAnimation) {

print("Start!")

}

}

KVC

CAAnimation 基于 OC 实现,以是 KVC KVO 都是可用的。

可以应用 KVC KVO 给 CAAnimation 工具设置 value,存取案例:

flyRight.setValue("form", forKey: "name")

flyRight.setValue(heading.layer, forKey: "layer")

//读取

guard let name = anim.value(forKey: "name") as? String else {

return

}

动画 Keys

在给 layer 添加 Animation 的时刻,有一个 key 参数,这个参数是用来指定动画的标示,让我们方便获取动画工具,以便以致在动画运行的时刻去节制它。

当多个动画各自自力履行的时刻,这些 Key 参数就可以发挥感化了。

履行中的动画

Layer 有一个措施 layer.animationKeys(),获取所有动画的数组

获取动画可以做:

履行 removeAllAnimations() 取消所有动画,或者 removeAnimation(forKey:) 根据 key 取消动画

经由过程 animationKeys() 遍历动画,获取的都是 immutable 工具,在他们履行的时刻并不能进行改动。

获取某一个动画经由过程 animationForKey(_:),获取的是 immutable 工具

6.3 动画组

多个动画打包成一个动画,多动画的同步,实现动画属性的统一治理。

当多个动画运行在一个 Layer 上面的时刻,很多时刻我们必要让这些动画互雷同步,应用 CAAnimationGroup 可以办理这个问题。外面上只是将多个动画合并,统一处置惩罚,背后的动画同步等机制,整个由 CAAnimationGroup 来完成。

实现如下:

//1️⃣:像正常创建 CABasicAnimation 一样创建 CAAnimationGroup,他们都是承袭自 `CAAnimation`,以是属性也有 `beginTime` `duration` `fillMode` `delegate` `isRemoveOnCompletion`。

let groupAnimation = CAAnimationGroup()

groupAnimation.beginTime = CACurrentMediaTime()

groupAnimation.duration = 0.5

groupAnimation.fillMode = kCAFillModeBackwards

//2️⃣:然后零丁创建三个 CABAsicsAnimation

let scaleDown = CABasicAnimation(keyPath: "transform.scale")

scaleDown.fromValue = 3.5

scaleDown.toValue = 1.0

let rotate = CABasicAnimation(keyPath: "transform.rotation")

rotate.fromValue = .pi/4.0

rotate.toValue = 0.0

let fade = CABasicAnimation(keyPath: "opacity")

fade.fromValue = 0.0

fade.toValue = 1.0

//3️⃣:着末经由过程对 group 动画设置动画数组的措施,分开的动画打成动画组,经由过程设置 groupAnimation 工具的 animations 属性,然后调用 layer 的 add 措施

groupAnimation.animations = [scaleDown, rotate, fade]

loginButton.layer.add(groupAnimation, forKey: nil)

然则说什么动画可以打包,什么动画必要自力编写,必要自己经由过程履历去衡量把握。比如一个启动界面的 ViewDidAppear 里面的动画,在刚进入界面的时刻开始,照样应该打成组的。

慢入慢出 EaseInOut

EaseInOut 在 UIView 的动画中经由过程设置调用 UIView 的 animate 措施中的 options 参数设置设置设备摆设摆设。

在 Layer 中也对照类似,只是语法上有一些差别,经由过程设置 Animation 工具的 timingFunction 属性来实现,这个属性是一 CAMediaTimingFunction 工具,承袭自 NSObject, 经由过程初始化措施指定 name 参数为一下四个预定义的值,即可创建预定义好的慢入慢出工具。

CAMediaTimingFunction 初始化措施的四个预定义 name 的值:

kCAMediaTimingFunctionLinear

kCAMediaTimingFunctionEaseIn

kCAMediaTimingFunctionEaseOut

kCAMediaTimingFunctionEaseInEaseOut

这四个函数跟前面 UIView 的慢入慢出类似,第一个是正常,第二个是慢入,第三个慢出,第四个慢入慢出。

慢如慢出动画的履行阶段

groupAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

我们可以创建自定义的 CAMediaTimingFunction 工具,经由过程 init 措施 controlPoints,传入四个贝赛尔曲线的两个节制点的坐标,即可以实现,不赘述。

动画重复 RepeatCount

设置动画的重复次数,即停止之后,重复从头开始动画,经由过程设置 CABasicAnimation 的属性 repeatCount,设置重复的次数。

别的的一个属性 autoreverses,设置自动逆向播放,动画完成之后,再逆向动画一次。

经由过程同时设置这两个参数,可以光阴轮回逆向播放动画。一轮正逆算 repeat 一次。

假如设置动画工具的 repeatCount 为 1.5,则动画的第二次动画的逆向动画取消,第二次只播放一次正向动画。

动画速率 speed

CABasicAnimation 的参数 speed,可以节制动画的速率,默认值为 1.0f。

着实:

动画的实际耗损光阴 * speed = duration

零丁设置 CABasicAnimation 工具的 speed 之外,还可以直接设置 Layer 的 speed,比如设置 self.view.layer.speed = 2.0,viewController 的 view 之下的所有动画都邑以 2.0 的速率播放。

您可能还会对下面的文章感兴趣: