Core Animation
Core Animation 在不消耗 CPU 负载的情况下(主要是用GPU)提供高帧率且流畅的动画。简单的配置一些参数就能达到你想要的效果。
CALayer
CALayer 管理基于图像内容的对象,并允许您在该内容上执行动画。
CALayer 经常用来为view 储存提供内容展示,但是也能脱离view 工作。Layer 除了具有 background color、 border、 和 shadow 这些属性之外还有几何空间属性 position、 size、 和 transform。
CALayer 对象还通过 CAMediaTiming 协议 封装了默认的动画属性
如果Layer 是通过 view 创建的 (创建view 的时候会附带创建跟view 绑定在一起的Layer 用来展示 view 的内容),view 自动成为layer的delegate 。如果是自己创建的,可以关联一个delegate ,通过delegate 对象动态提供layer 内容。
创建一个 Layer
init()
init(layer:) //此方法不常使用
//设置和获取Layer 的 delegate
var delegate: CALayerDelegate?
提供Layer内容
//设置Layer 内容
var contents: Any? { get set }
如果你要展示一个静态图片,可以使用CGImage 设置这个属性。设置这个属性Layer 会直接是用这个image 而不是再创建空间去存贮这个image.如果Layer与view相关联,则尽量避免设置这个数学,因为layer 与 view 之间的相互作用很可能会更新layer的内容,从而替换掉你已经设置的值。
//获取Layer 内容的 rect
var contentsRect: CGRect { get set }
//设置layer 的拉伸区域,其实跟image设置拉伸区域是一个道理 rect 的值为 0-1 之间
var contentsCenter: CGRect { get set }
设置为(0.25,0.25) (0.5,0.5) 时
//重载layer 的内容
func display()
不要直接调用这个方法,这个方法是用来Layer 在需要的时候调用来更新自己的内容的。如果Layer 存在delegate时,将会调用delegate 的 display(_:) 方法,如果delegate 没有实现这个方法,那么穿件一个存储区域,调用Layer 的 draw(in:) 方法讲content 填充到创建的存储区域中。
CALayer 的子类可以重写次方法,来直接设置它的内容
//绘制Layer 内容到上下文中
func draw(in ctx: CGContext)
改变Layer的展示
//指定Layer 的内容如何在其边界内定位或缩放
var contentsGravity: String { get set }
kCAGravityResize
kCAGravityCenter
kCAGravityBottom
kCAGravityTopLeft
//Layer是否为隐式翻转
func contentsAreFlipped() -> Bool
//不透明性
var opacity: Float { get set }
//是否隐藏
var isHidden: Bool { get set }
//是否剪除sublayers 超过Layer本身的部分
var masksToBounds: Bool { get set }
如果设置值为true ,Core Animation 会创建一个隐式的遮罩层来罩在Layer 的bounds 的范围内。如果mask 属性已经被指定那么两个遮罩将会混合得到最终的遮罩。
//为layer 设置遮罩,遮罩不能含有superlayer,否则结果无法预料
var mask: CALayer? { get set }
//Layer 是否具有双面可见性,如果设置为fales即背面看不到(在翻转时 可以看出效果)
var isDoubleSided: Bool { get set }
//Layer 圆角 这个属性是作用在Layer的背景上的,配合masksToBounds 使用才行
var cornerRadius: CGFloat { get set }
//遮罩层角
var maskedCorners: CACornerMask { get set }
//边界线宽
var borderWidth: CGFloat { get set }
//边界线颜色
var borderColor: CGColor? { get set }
//背景色
var backgroundColor: CGColor? { get set }
//阴影的不透明度
var shadowOpacity: Float { get set }
//阴影半径 默认值为3.0
var shadowRadius: CGFloat { get set }
//阴影偏移
var shadowOffset: CGSize { get set }
//阴影颜色
var shadowColor: CGColor? { get set }
//阴影路径
var shadowPath: CGPath? { get set }
//是否支持边缘抗锯齿
var allowsEdgeAntialiasing: Bool { get set }
//是否支持分离组
var allowsGroupOpacity: Bool { get set }
开启CALayer的 allowsGroupOpacity 属性后,子 layer 在视觉上的透明度的上限是其父 layer 的 opacity (对应UIView的 alpha ),并且从 iOS 7 以后默认全局开启了这个功能,这样做是为了让子视图与其容器视图保持同样的透明度
Layer 滤镜
//获取和设置滤镜
var filters: [Any]? { get set }
//混合滤镜
var compositingFilter: Any? { get set }
var backgroundFilters: [Any]? { get set }
//缩小
var minificationFilter: String { get set }
var minificationFilterBias: Float { get set }
//放大
var magnificationFilter: String { get set }
Layer 的渲染
//是否是不透明的(注意与hidden 和 alpha 之间的区别),该属性决定了两个视图是否是叠加显示
var isOpaque: Bool { get set }
//抗锯齿属性,默认为开启状态
var edgeAntialiasingMask: CAEdgeAntialiasingMask { get set }
//Layer Y轴是否隐式翻转
func contentsAreFlipped() -> Bool
//是否几何空间旋转
var isGeometryFlipped: Bool { get set }
//是否异步绘制
var drawsAsynchronously: Bool { get set }
//是否光栅化(把layer保存为bitmap,下次直接使用,适用于静态不变的)
var shouldRasterize: Bool { get set }
//栅格化抗锯齿
var rasterizationScale: CGFloat { get set }
//内容格式
var contentsFormat: String { get set }
//渲染到指定上下文
func render(in ctx: CGContext)
let diameter: CGFloat = 100
let rect = CGRect(origin: CGPoint.zero,
size: CGSize(width: diameter, height: diameter))
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.lineWidth = 10
shapeLayer.path = CGPath(ellipseIn: rect,
transform: nil)
let renderer = UIGraphicsImageRenderer(size: rect.size)
let image = renderer.image {
context in
return shapeLayer.render(in: context.cgContext)
}
Layer 的几何空间属性
//layer 在父坐标系 的 position 和 size ,属于计算属性由bounds 、 anchorPoint 和 position 计算出来
var frame: CGRect { get set }
var bounds: CGRect { get set }
//位置 相对于锚点
var position: CGPoint { get set }
//z轴位置
var zPosition: CGFloat { get set }
//Z锚点
var anchorPointZ: CGFloat { get set }
//锚点 默认值为(0.5,0.5)
var anchorPoint: CGPoint { get set }
//比例因子(可用来去除锯齿化)
var contentsScale: CGFloat { get set }
Layer 的变换 Transform
//Transform 都与锚点有关
var transform: CATransform3D { get set }
var sublayerTransform: CATransform3D { get set }
//Layer 的仿射变换(同View 的transform)
func affineTransform() -> CGAffineTransform
//设置Layer的仿射变换
func setAffineTransform(_ m: CGAffineTransform)
Layer 的层级结构
//子Layer
var sublayers: [CALayer]? { get set }
//父Layer
var superlayer: CALayer? { get }
//添加Layer
func addSublayer(_ layer: CALayer)
//从父Layer中移除
func removeFromSuperlayer()
//插入一个子Layer
func insertSublayer(_ layer: CALayer, at idx: UInt32)
//替换子Layer
func replaceSublayer(_ layer: CALayer, with layer2: CALayer)
Layer 刷新
//标记Layer 需要刷新(会调用delegate 的 display(_:) 或 draw(_:in:)方法)
func setNeedsDisplay()
//标记指定范围内需要刷新
func setNeedsDisplay(_ r: CGRect)
//改变内容后自动调用 setNeedsDisplay()
var needsDisplayOnBoundsChange: Bool { get set }
//如果Layer 当前被标记需要刷新,则调用 setNeedsDisplay()
func displayIfNeeded()
//Layer 是否需要刷新
func needsDisplay() -> Bool
//可以用来重写指定某属性改变后刷新 Layer
class func needsDisplay(forKey key: String) -> Bool
Layer 动画
//添加动画
func add(_ anim: CAAnimation, forKey key: String?)
//获取指定Key 的动画
func animation(forKey key: String) -> CAAnimation?
//移除所有动画
func removeAllAnimations()
//移除指定动画
func removeAnimation(forKey key: String)
//获取Layer 当前绑定动画的Key
func animationKeys() -> [String]?
Layer 的布局管理
//布局约束管理对象(mac OS 下才能使用)
var layoutManager: CALayoutManager? { get set }
//更新Layer 子layer 的约束
func setNeedsLayout()
//更新约束
func layoutSublayers()
func layoutIfNeeded()
//是否需要更新约束
func needsLayout() -> Bool
//自动调整尺寸(mac OS 下才能使用)
var autoresizingMask: CAAutoresizingMask { get set }
Layer 坐标转换
//从其他Layer 转换到此layer
func convert(_ p: CGPoint, from l: CALayer?) -> CGPoint
//将本Layer 点转换到指定Layer
func convert(_ p: CGPoint, to l: CALayer?) -> CGPoint
//转换rect
func convert(_ r: CGRect, from l: CALayer?) -> CGRect
func convert(_ r: CGRect, to l: CALayer?) -> CGRect
//时间节点转换
func convertTime(_ t: CFTimeInterval, from l: CALayer?) -> CFTimeInterval
func convertTime(_ t: CFTimeInterval, to l: CALayer?) -> CFTimeInterval
Layer Scrolling
//可见区域
var visibleRect: CGRect { get }
//滚动到指定点
func scroll(_ p: CGPoint)
//滚动到指定区域
func scrollRectToVisible(_ r: CGRect)