此框架把屏幕上的內容組合起來,這個內容被分解成圖層,放到圖層樹中,這個樹造成了你能在應用程序看到的內容的基礎html
圖層在iOS中就是CALayer
類
當咱們建立一個UIView
類的時候就會同時建立這個類的layer
屬性。 而UIView
和CALayer
分工明確。ios
UIView
類確切的知道響應鏈,能夠響應事件。
UIView
封裝了CALayer的部分功能。好比UIView
中的frame
、center
屬性對應CALayer
中的frame
、position
。
UIView
還封裝了高級API使動畫更簡單。
UIView
還具備自動排版、佈局的功能git
CALayer
是UIView
的內部實現細節,真正負責屏幕上的顯示和動畫。
CALayer
的部分屬性並無被UIView
暴露。好比:
~ 陰影、圓角、帶顏色的邊框
~ 3D變換(後面會講到UIView
只能夠作仿射變換)
~ 透明遮罩算法
最好使用使用視圖而不是單獨的圖層的緣由之一有:視圖能夠進行自動佈局,自適應屏幕的翻轉。而圖層是作不到這樣的框架
對於什麼時候使用CALayer
。能夠參考以下條件:ide
UIView
提供的動畫方案不能知足你的要求函數
須要使用 UIView
沒有暴露的CALayer
的屬性佈局
使用CALayer的特定子類,提升應用性能(後面會講到CAShaperLayer
、CATiledLayer
等等)性能
Core Animation
以前須要先講講一些基礎知識anchorPoint
。是相對值,而不是絕對值。即便大小改變,也不用調整contents
屬性※ contentsGravity動畫
※ contentsScale
※ contentsRect
※ contentsCenter
在開發中蘋果建議在UIView中不要實現一個空的drawRect:方法。這是由於實現這個方法的View會生成一個寄宿圖。這個寄宿圖就是CALayer的contents屬性。
contentsGravity
是控制內容在邊界內如何對齊。對應UIView中的contentMode屬性。可選的類型就是top、left、right、center、aspect、fill 等等。
contentsScale
就是代表寄宿圖圖片的精度大小。1.0就是每一個點繪製一個像素。2.0就是每一個點繪製兩個像素。就是retain屏幕。
tip:contentsGravity設置的選項是沒有拉伸圖片的話,這個屬性的設置纔會有顯而易見的效果。
contentsRect
使用的是單位座標。指定一個矩形,範圍外的圖片會被裁剪。而後用矩形內的內容進行填充
contentsCenter
使用的是單位座標。定義了一個固定的邊框和一個在圖層上可拉伸的區域。
例如:設置爲{0.25,0.25,0.5,0.5},那麼圖層的四個邊角的內容不變,而其餘區域內容在圖層大小(由contentsGravity決定)改變的時候就可拉伸。
佈局
frame
表明了圖層的外部座標(在父圖層上佔用的空間),bounds
是內部座標,center和position表明了本圖層的anchorPoint
在父圖層的位置錨點anchorPoint
使用的是單位座標,默認值爲{0.5,0.5}.
frame
爲{0,0,100,100},則position
初始化爲{0,0,50,50},若是改變anchorPoint
的值爲{0,0},則圖層左上角爲錨點,左上角的點就在position
的位置frame
的值和bounds
、position
和transform
密切相關。改變其中一個值同時會改變其餘的值。
當圖層進行transform旋轉以後,frame表明的區域是整個軸對齊的區域
座標系
position
依賴於它的父圖層的bounds
。若是父圖層發生移動,子圖層也會跟着移動bounds
來實現內容滾動的效果zPosition
和anchorPointZ
經過增長圖層的zPosition
,就能夠把圖層前置,到達小於它的zPosition
值的圖層的前面。
zPosition
只能改變顯示順序,不能改變響應順序。響應順序仍是按照addSubLayer
的順序
可能會用到的API
把一個圖層座標系下的點或矩形裝換成另外一個圖層或座標系的點
- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer; - (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer; - (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer; - (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;
//接受一個在本圖層座標系下的點,若是這個點在圖層範圍內就返回YES - (BOOL)containsPoint:(CGPoint)p;
//返回能接收這個點的最遠CALayer子代。若是這個點在最外面圖層的範圍以外,則返回nil //若是設置了zPosition,返回的就不必定是最前方的Layer - (CALayer *)hitTest:(CGPoint)p;
× 圓角cornerRadius
maskToBounds
會依此屬性截取× 圖層邊框borderColor
、borderWidth
bounds
繪製,在全部子圖層以前bounds
變化,而不是圖層內容× 陰影shadowOffset
、shadowColor
shadowOffset
是CGSize
類型的值。寬度控制橫向的移動,高度控制縱向的移動
shadowRadius
屬性控制着陰影的模糊度,數值越大越模糊和天然
shadowPath
是CGPathRef
類型。單獨於圖層形狀以外指定陰影的形狀
與直接指定
shadowPath
相比,圖層的陰影根據圖層內容動態計算陰影的形狀。比較消耗性能
由於圖層的陰影老是在圖層範圍外,因此直接使用
maskToBounds
的時候會把陰影給裁剪掉。
1、能夠添加一個專門顯示陰影的圖層來獲得maskToBounds
+shadow
的效果
2、指定shadowPath
× 圖層蒙版mask
屬性 —— 是一個CALayer類型,定義了父圖層的部分可見區域。
mask
圖層最重要的是它的輪廓,賦值了mask屬性,就會按照mask圖層的形狀把父視圖進行切割,保留mask
圖層內的父視圖內容,捨棄圖層外的父視圖內容
× 拉伸過濾Filter
—— 當圖片須要顯示不一樣大小的時候,拉伸過濾的算法就起到做用了。CALayer有三種過濾算法
kCAFilterTrilinear
默認的過濾算法爲linear,trilinear比 linear可以更好的支持大圖;對於比較小的圖或者是差別特別明顯,極少斜線的大圖,使用Neareset能夠呈現更好的效果。
× 組透明GroupOpacity
——整個圖層樹有一個總體的透明效果仍是進行透明度的混合疊加
× 光柵化shouldRasterize
—— YES表明圖層及其子圖層會被整合成一個總體的圖片
使用了shouldRasterize
,就要同步設置rasterizationScale
來匹配屏幕
layer.rasterizationScale = [UIScreen mainScreen].scale;
→ 仿射變換affineTransform
:
是`CGAffineTransform`類型。`Core Graphics`框架對象。提供以下函數建立:
CGAffineTransformMakeRotation(CGFloat angle) CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
使用以下函數,初始化生成一個什麼都不作的變換,也就是建立一個
CGAffineTransform
類型的空值,矩陣論中稱做單位矩陣
CGAffineTransformIdentity
混合兩個已經存在的變換矩陣,使用以下方法,在兩個變換的基礎上建立一個新的變換:
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);
UIView
能夠經過transform
屬性作變換,對應CALayer
的affineTransform
屬性
tip:旋轉常量M_PI是一個弧度單位。弧度用數學常量pi的倍數表示。能夠用如下公式進行弧度角度換算
#define DEGREES_TO_RADIANS(x) ((x)/180.0 *M_PI)
這裏要注意的是:旋轉的時候會尋找最短路徑進行旋轉。好比弧度大於pi,就會逆時針旋轉
混合變換 —— 使用如下函數能夠在一個變換的基礎上作更深層次的變換
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle) CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy) CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
注意:變換的順序很重要,先旋轉再平移和先平移再旋轉的結果是不一樣的
→ 3D變換transform3D
CALayer的transform
屬性是CATransform3D
類型,是一個4x4的矩陣,聲明以下
struct CATransform3D { CGFloat m11, m12, m13, m14; CGFloat m21, m22, m23, m24; CGFloat m31, m32, m33, m34; CGFloat m41, m42, m43, m44; };
提供的建立函數
看起來和affineTransform相似,可是平移和縮放多了一個 z 參數,旋轉除了弧度參數,還多了x、y、z 三個參數,分別表明每一個方向軸的旋轉
CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z) CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz) CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)
z軸和x軸、y軸分別垂直,指向手機用戶爲正方向.繞z軸的旋轉就等同於二維的仿射旋轉,繞x軸和y軸的旋轉就突破了二維的空間。
scale中的參數若是爲負數先按軸翻轉再進行縮放
接下來就說說怎麼在應用顯示擬真的3D效果
透視投影
爲了修正視圖的遠近不一樣的縮放比例,咱們引入投影變換
。經過修改矩陣中的m34
元素控制
m34
的默認值是0,咱們能夠經過設置m34
爲-1.0 / d
來應用透視效果,d
表明了想象中視角相機和屏幕之間的距離,以像素爲單位。不須要計算,只須要估算一個就行了。一般500-1000就很好了。
減小距離的值會加強透視效果,而一個很是大的值會讓它基本失去透視效果
當視圖遠離觀察者的時候物體會變小變遠,當遠離到必定距離的時候,就縮成了一個點,因而視角內的全部物體都匯聚消失在了同一個點。
接下來就說說關於這個點的事
滅點
在現實中,這個點一般是物體的中點,爲了在應用中建立擬真效果 ,這個點應該是屏幕中點,或者至少是全部3D對象的中心點
CAAnimation
定義了這個點在變換圖層的anchorPoint
(一般位於圖層中心,但也有例外),當圖層發生變換的時候,這個點永遠是變換以前的anchorPoint
位置
改變position
就改變了圖層的anchorPoint
,因此爲了讓全部3D視圖共用一個滅點,能夠先把視圖放在屏幕中央,而後經過變換移動到指定位置
幸運的是,蘋果已經幫助咱們把上面這個比較繁瑣的事情封裝了
sublayerTransform
屬性
是一個CATransform3D
類型。它影響到所有子圖層。如此咱們能夠統一設置子圖層的透視變換和共享滅點。
其餘關於3D的屬性
當把視圖繞着Y軸旋轉180度,咱們就能夠看到視圖的背面。繪製的就是視圖的鏡像。能夠經過doubleSided
設置是否繪製視圖背面。
[ ] 1.繞Z軸旋轉的兩個圖層作相反的旋轉操做,第二個圖層作的旋轉會被第一個圖層旋轉抵消。
[ ] 2.而繞X軸和Y軸旋轉的不一樣圖層作相反的旋轉操做並不會相互抵消。
緣由是儘管
Core Animation
圖層存在於3D空間以內,但它們並不都存在同一個3D空間。每一個圖層的3D場景實際上是扁平化的,當你從正面觀察一個圖層,看到的實際上由子圖層建立的想象出來的3D場景
至少當你用正常的CALayer的時候是這樣,CALayer有一個叫作CATransformLayer的子類能夠解決這個問題
→ 固體對象