Core Animation-CALayer

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) 时

image.png
//重载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 }

image.png

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 }

image.png
//抗锯齿属性,默认为开启状态
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)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容