本文是要點(diǎn)型筆記,建議先閱讀以下參考內(nèi)容后再閱讀,完成知識(shí)體系的構(gòu)建:
[1] View Programming Guide for iOS
[2] Core Animation Programming Guide
[3] ios核心動(dòng)畫高級(jí)技巧
[4] 通過實(shí)現(xiàn)一個(gè)TableView來理解IOS UI編程
[5] 詳解 CALayer 和 UIView 的區(qū)別和聯(lián)系
[6] iOS繪圖教程
[7] Quartz 2D編程指南之一~十三 - 南峰子
LayerKit => Core Animation是一個(gè)復(fù)合引擎,它的職責(zé)就是盡可能快地組合屏幕上不同的可視內(nèi)容咽笼,可視內(nèi)容(圖片、文本、背景色抚官、…)被分解成獨(dú)立的圖層,存儲(chǔ)在一個(gè)叫做【圖層樹】的體系之中阶捆。
圖層可以通過【寄宿圖】來提供可視內(nèi)容凌节,通過【圖層幾何學(xué)/布局特性】鎖定擺放的位置,可以加一些基礎(chǔ)【視覺效果】(圓角洒试、邊框倍奢、陰影、蒙版垒棋、拉伸卒煞、透明…)或高級(jí)視覺效果-【變換】(仿射、3D)叼架;除了圖片和背景純色之外畔裕,CA還提供了一系列【專有圖層】對(duì)繪制能力進(jìn)行了擴(kuò)展衣撬,針對(duì)特殊場(chǎng)景進(jìn)行了封裝和性能優(yōu)化。
注:優(yōu)先級(jí)-displayLayer: > -drawInContext: > -drawLayer:inContext: > -drawRect:
附 UIKit & Quarts 2D:
第一章:圖層的樹狀結(jié)構(gòu)
1. 四個(gè)平行的層級(jí)關(guān)系
視圖樹 —— UIView扮饶,著重于交互-響應(yīng)事件(觸摸/手勢(shì)…)具练,作為CALayer的管理者
模型樹/邏輯樹(目標(biāo)幀) —— CALayer - modelLayer(),不涉及響應(yīng)鏈(通過視圖層級(jí)關(guān)系傳遞觸摸事件的機(jī)制)
呈現(xiàn)樹/動(dòng)畫樹(當(dāng)前幀) —— presentationLayer(), 動(dòng)畫過程中的當(dāng)前值甜无,詳見第七章
渲染樹/顯示樹(下一幀) —— 圖層和動(dòng)畫打包提交到渲染服務(wù)后反序列化所得樹扛点,被用于生成gl三角形s,詳見第十二章
2. CALayer和UIView的區(qū)別和聯(lián)系
- 兩者通過UIView的
layerClass類方法
和layer屬性
聯(lián)系在一起 - 屬性封裝 - Layer 的 frame 是由 anchorPoint,position,bounds和 transform 共同決定的岂丘,而View 只是簡(jiǎn)單的返回 Layer的 frame(bounds和center/position類似)
- 分工 - UIView側(cè)重對(duì)顯示內(nèi)容的管理陵究,而CALayer側(cè)重顯示內(nèi)容的繪制(drawXxx())和顯示(display())
- 事件響應(yīng) - UIResponder決定了UIView能接受并響應(yīng)事件,而CALayer不可以(即使有Hit Testing方法)
-
隱式動(dòng)畫 - 非根CALayer 支持隱式動(dòng)畫奥帘,而UIView 作為 Layer 的默認(rèn)代理铜邮,通過在actionForLayer:forKey:返回nil默認(rèn)禁止了隱式動(dòng)畫(在animation block中會(huì)自動(dòng)重新啟用,本質(zhì):
[CATransaction setDisableActions:NO];
) -
視圖未暴露的CALayer的功能:
- 錨點(diǎn)翩概、陰影,圓角,邊框牲距、透明遮罩
- 非矩形范圍(mask or shadowPath?钥庇?牍鞠?)
- 3D變換(
UIView的transform;)CALayer的transform和affineTransform - 多級(jí)非線性動(dòng)畫(UIView的默認(rèn)顯式動(dòng)畫都是線性動(dòng)畫)
3. CALayer和UIView的選擇
UIView的適用場(chǎng)景
- 優(yōu)先使用,原因:自動(dòng)排版/布局和事件處理
CALayer的適用場(chǎng)景:
可以在Mac OS上運(yùn)行的跨平臺(tái)應(yīng)用- 使用多種CALayer的子類(見第六章)评姨,并且不想創(chuàng)建額外的UIView去包封裝它們
- 對(duì)性能要求特別高 => 考慮用CALayer或OpenGL繪圖
第二章:設(shè)置寄宿圖 - 給圖層提供內(nèi)容
第三章:圖層幾何學(xué)
- 布局屬性 - 在圖層級(jí)別無法根據(jù)兄弟圖層控制位置和尺寸
- frame(外 - 父圖層坐標(biāo)系)
- bounds(內(nèi) - 自身坐標(biāo)系)
- anchorPoint - 錨點(diǎn)在自身坐標(biāo)系中的(x,y) - 最佳實(shí)例:時(shí)鐘應(yīng)用中的指針轉(zhuǎn)動(dòng)
- center(UIView)/position(CALayer) - ?錨點(diǎn)在父圖層坐標(biāo)系中的(x,y)
第四章:視覺效果
- 圓角 - conrnerRadius
- 只影響背景顏色
而不影響背景圖片或是子圖層 - 通常結(jié)合masksToBounds使用难述,來裁剪子圖層和背景圖片
- 只影響背景顏色
- 圖層邊框 - borderWidth和borderColor
- 邊框是繪制在圖層邊界里面的,而且在所有子內(nèi)容之前吐句,也在子圖層之前胁后。
- 實(shí)現(xiàn)邊框不遮擋內(nèi)容的兩種做法
- 使用帶邊框效果的寄宿圖
- 讓邊框和內(nèi)容解除父子關(guān)系,并讓內(nèi)容在圖層樹中靠前
-
陰影 -
shadowOpacity嗦枢、shadowColor攀芯、shadowOffset(方向和距離)和shadowRadius(模糊度)- 與邊框不同
- 圖層的陰影繼承自內(nèi)容(包含寄宿圖和子視圖)的外形,而不是根據(jù)邊界和角半徑來確定文虏。
- 陰影可能在圖層邊界之外侣诺;會(huì)被masksToBounds裁剪掉
- 解決方案:使用兩個(gè)圖層(一個(gè)只畫陰影的空的外圖層和一個(gè)用masksToBounds裁剪內(nèi)容的內(nèi)圖層)
- shadowPath - 提高性能,CGPathRef類型
- CGPathCreateMutable+CGPathMoveToPoint+CGPathAddXxx
- UIBezierPath類 + addXxx方法
- 與邊框不同
-
圖層蒙板
- mask - 類似于一個(gè)子圖層氧秘,但它定義的是父圖層的部分可見區(qū)域
- 比conrnerRadius+masksToBounds更靈活:蒙板圖不局限于靜態(tài)圖年鸳,以通過編碼甚至動(dòng)畫的方式實(shí)時(shí)生成,而且讓子圖層或子視圖裁剪成同樣的形狀
拉伸過濾
- 較小的圖或者是差異特別明顯丸相、極少斜線的大圖搔确,Nearest會(huì)保留這種差異明顯的特質(zhì)以呈現(xiàn)更好的結(jié)果
- 對(duì)于大多數(shù)的圖尤其是有很多斜線或曲線輪廓的圖片,選用kCAFilterLinear或kCAFilterTrilinear
- 組透明
- alpha(UIView)、opacity(CALayer)都會(huì)影響子層級(jí)的
組透明設(shè)置造成的像素合成 - 組透明整體實(shí)現(xiàn)方案(解決上述透明度混合造成顯示不一致的問題)
- UIViewGroupOpacity -> YES(Info.plist)
- allowsGroupOpacity(IOS7+可用膳算,相當(dāng)于UIViewGroupOpacity)
- shouldRasterize+rasterizationScale(配置屏幕)座硕,如果它被設(shè)置為YES,在應(yīng)用透明度之前畦幢,圖層及其子圖層都會(huì)被整合成一個(gè)整體的圖片
- alpha(UIView)、opacity(CALayer)都會(huì)影響子層級(jí)的
第五章:變換
- CGAffineTransform
- “仿射”:圖層中平行的兩條線在變換之后仍然保持平行
- 混合變換 - 變換的順序會(huì)影響最終的結(jié)果坎吻,也就是說旋轉(zhuǎn)之后的平移和平移之后的旋轉(zhuǎn)結(jié)果可能不同
- CATransform3D
- 透視投影 - m34 = -1.0/d缆蝉,d代表了假想中視角相機(jī)和屏幕之間的距離宇葱,通常設(shè)置為500~1000
- 滅點(diǎn) - anchorPointZ+anchorPoint,旋轉(zhuǎn)和縮放的不變點(diǎn) => sublayerTransform
- 背面 - doubleSided屬性刊头,區(qū)別:doubleSided不影響事件響應(yīng)黍瞧,設(shè)置hidden或alpha為0不會(huì)響應(yīng)事件
- 固體對(duì)象
- 光亮和陰影 - GLKMatrix3Xxx和GLKVector3Xxx方法
- 如何讓圖層順序靠前(響應(yīng)鏈中靠后)的圖層得到事件響應(yīng)
- bringSubviewToFront、sendSubviewToBack原杂、exchangeSubviewAtIndex(_:withSubviewAtIndex:)等方法可以同時(shí)改變顯示順序和圖層順序(響應(yīng)鏈優(yōu)先級(jí))
- 通過將優(yōu)先級(jí)更高的UIView的userInteractionEnabled設(shè)置為NO
第六章:專用圖層 +(Class)layerClass
-
CAShapeLayer - 通過矢量圖形而不是bitmap來繪制寄宿圖的圖層子類
- 相比在CALayer中繪制路徑而言優(yōu)勢(shì)如下:
- 渲染快速(硬件加速)
- 高效使用內(nèi)存(不需要寄宿圖)
- 不會(huì)被圖層邊界剪裁掉(可以在邊界之外繪制)
- 不會(huì)出現(xiàn)像素化(因?yàn)槭鞘噶繄D形)
- 屬性
- fillColor印颤、strokeColor、lineWidth(單位:點(diǎn))穿肄、lineCap年局、lineJoin
- path - UIBezierPath.CGPath
- 圓角 - 相比使用cornerRadius更靈活
- 相比在CALayer中繪制路徑而言優(yōu)勢(shì)如下:
-
CATextLayer - 使用了Core text,渲染非诚滩快
- 屬性
- string - (富文本使用NSAttributedString)
- font 和 fontSize矢否、
wrapped(自動(dòng)換行)、truncationMode(截?cái)嗄J?脑溢、alignmentMode
- 文本像素化
- 屬性
textLayer.contentsScale = UIScreen.mainScreen().scale
- UILabel替代品 - 用CATextLayer作為宿主圖層的UILabel子類僵朗,可以隨著視圖自動(dòng)調(diào)整大小而且也沒有冗余的寄宿圖
-
- 不能顯示自己的內(nèi)容,只有當(dāng)存在了一個(gè)能作用于子圖層的變換它才真正存在屑彻,而且變換將對(duì)所有子圖層的3D場(chǎng)景生效而不是扁平化后的子圖層验庙。
- CATransformLayer并不平面化它的子圖層,所以它能夠用于構(gòu)造一個(gè)層級(jí)的3D結(jié)構(gòu)
-
CAGradientLayer
- 用來生成兩種或更多顏色平滑漸變社牲,繪制使用了硬件加速
- 基礎(chǔ)漸變
- startPoint和endPoint
- colors(CGColorRef數(shù)組)
- 多重漸變
- locations屬性
- 以NSNumber包裝的浮點(diǎn)數(shù)值數(shù)組粪薛,定義了colors屬性中每個(gè)不同顏色的位置(以單位坐標(biāo)系標(biāo)定)
- 確保數(shù)組大小和colors數(shù)組大小一定要相同
-
- 高效生成許多相似的圖層,并在每個(gè)復(fù)制體上應(yīng)用不同的變換搏恤。
- 屬性
- instanceCount
- instanceTransform
- instanceRed/Green/BlueOffset违寿、instanceAlphaOffset
- ……
- 反射 - ReflectionView
-
- -scrollToPoint:方法,自動(dòng)適應(yīng)bounds的原點(diǎn)以便圖層內(nèi)容出現(xiàn)在滑動(dòng)的地方
并不負(fù)責(zé)將觸摸事件轉(zhuǎn)換為滑動(dòng)事件挑社,既不渲染滾動(dòng)條陨界,也不實(shí)現(xiàn)任何iOS指定行為例如滑動(dòng)反彈(當(dāng)視圖滑動(dòng)超多了它的邊界的將會(huì)反彈回正確的地方)。- UIScrollView并沒有用CAScrollLayer痛阻,事實(shí)上菌瘪,就是簡(jiǎn)單的通過直接操作圖層邊界來實(shí)現(xiàn)滑動(dòng)。
var visibleRect: CGRect { get }
func scrollPoint(_ p: CGPoint) // 從圖層樹中查找并找到第一個(gè)可用的CAScrollLayer,然后滑動(dòng)它使得指定點(diǎn)成為可視的
func scrollToRect(_ r: CGRect) // 類似俏扩,不過是使指定矩形可視
-
CATiledLayer
- OpenGL有一個(gè)最大的紋理尺寸(通常是20482048或40964096糜工,這個(gè)取決于設(shè)備型號(hào)),如果你想在單個(gè)紋理中顯示一個(gè)比這大的圖录淡,即便圖片已經(jīng)存在于內(nèi)存中了捌木,你仍然會(huì)遇到很大的性能問題。所以需要使用類似CATiledLayer的技術(shù)
-(void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx //在此根據(jù)需要加載不同的tile
class func fadeDuration() -> CFTimeInterval
tileLayer.contentsScale = [UIScreen mainScreen].scale;
CAEmitterLayer看上去像是許多CAEmitterCell的容器嫉戚,這些CAEmitierCell定義了一個(gè)例子效果刨裆。你將會(huì)為不同的例子效果定義一個(gè)或多個(gè)CAEmitterCell作為模版,同時(shí)CAEmitterLayer負(fù)責(zé)基于這些模版實(shí)例化一個(gè)粒子流彬檀。一個(gè)CAEmitterCell類似于一個(gè)CALayer:它有一個(gè)contents屬性可以定義為一個(gè)CGImage帆啃,另外還有一些可設(shè)置屬性控制著表現(xiàn)和行為。
- 一個(gè)高性能的粒子引擎窍帝,被用來創(chuàng)建實(shí)時(shí)粒子動(dòng)畫如:煙霧努潘,火,雨等等這些效果坤学。
- 自身屬性
+ emitterCells
+ preservesDepth
+ renderMode
- kCAEmitterLayerAdditive是疊加效果疯坤,其他是覆蓋效果
- [CAEmitterCell](https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CAEmitterCell_class/)的屬性
+ contents、color
+ birthRate
+ lifetime 深浮、lifetimeRange - 類似velocity
+ alphaSpeed
+ velocity压怠、velocityRange - [velocity~(velocity+velocityRange)]定義了速度變化范圍
+ emissionLatitude(z軸)、emissionLongitude(xy平面)略号、emissionRange(環(huán)繞發(fā)射角度的一個(gè)圓錐范圍)
-
CAEAGLLayer
- OpenGL沒有對(duì)象或是圖層的繼承概念刑峡,它的全部工作就是處理3D空間中有顏色和紋理的三角形
- GLKView(GLKit框架) + CAEAGLLayer(QuartzCore)
- 重要元素
class func setCurrentContext(_ context: EAGLContext!) -> Bool
func renderbufferStorage(_ target: Int, fromDrawable drawable: EAGLDrawable!) -> Bool
func presentRenderbuffer(_ target: Int) -> Bool
+ CAEAGLLayer的[drawableProperties屬性](https://developer.apple.com/library/ios/documentation/iPhone/Reference/EAGLDrawable_Ref/index.html#//apple_ref/occ/intfp/EAGLDrawable/drawableProperties)(EAGLDrawable協(xié)議)
+ [GLKBaseEffect](https://developer.apple.com/library/ios/documentation/GLkit/Reference/GLKBaseEffect_ClassRef/) - 著色邏輯:func prepareToDraw()
+ glXxx系列方法(setupBuffers & drawFrame)
-
AVPlayerLayer
- 由AVFoundation框架提供 (不同于其他CALayer由Core Animation框架提供)
- 播放控制和展現(xiàn)分離:AVPlayer和AVPlayerLayer
- AVPlayer - play()、pause()玄柠、rate等
-
AVPlayerLayer - player屬性和init(player player: AVPlayer)
- 繼承了父類CALayer的所有特性突梦,不會(huì)受限于要在一個(gè)矩形中播放視頻;
- 可實(shí)現(xiàn)3D羽利、圓角宫患、有色邊框、蒙板这弧、陰影等效果