CoreAnimation With Swift(1)--理論

CoreAnimation

本次教程分為兩個部分,分別為理論和實戰(zhàn),實戰(zhàn)部分,主要就是一些代碼,對理論部分的解析,下面讓我們進入下面我們的第一部分CoreAnimation With Swift 理論

CALayer基礎(chǔ)

UIView之所以能顯示在屏幕上,完全是因為它內(nèi)部的一個圖層.當UIView需要顯示到屏幕上時,會調(diào)用drawRect:方法進行繪圖,并且會將所有內(nèi)容繪制在自己的圖層上,繪圖完畢后,系統(tǒng)會將圖層拷貝到屏幕上,于是就完成了UIView的顯示。CALayer是用來管理位圖的state,以及如何被渲染出來。

CALayer基本屬性

CALayeranchorpoint是圖層的關(guān)鍵,anchorpoint的位置發(fā)生變化,包括CALayerposition等屬性相應(yīng)的就會發(fā)生變化。anchorpoint是用單位坐標的(x,y軸都是從0到1,默認的anchorpoint的坐標為(0.5,0.5))

position:CGPoint用來設(shè)置CALayer在父層中的位置
anchorPoint:CGPoint決定著CALayer身上的哪個點會在position屬性所指的位置

contentsGravity

當圖片大小不是適合當前view的時候,你可能會使用view.contentMode來設(shè)置縮放和位置,其實他是通過控制CALayercontentGravity屬性來實現(xiàn)的

contentsScale

由于layer不能區(qū)分分辨率,contentScale用來定義像素尺寸到layer尺寸的拉伸比率,默認值是1

contentsRect

contentsRect使用的是單位坐標,表示的是需要顯示的內(nèi)容的尺寸

contentsCenter

contentsCenter:CGRect定義了layer內(nèi)部一個可以被拉伸的區(qū)域,外部則是一個固定的邊界。這個屬性將一個layer分為9個部分。根據(jù)contentsGravity的設(shè)定,拉伸相應(yīng)地區(qū)域??梢詤⒖嘉⑿帕奶煊涗浬夏莻€氣泡

layer的視覺效果

圓角

CALayer有一個cornerRadius屬性用來制作layer的圓角,默認情況下該屬性只作用于backgroundColor,而對于sublayer和背景圖都沒有效果,但是如果配合masksToBounds=YES的設(shè)置,可以對layer內(nèi)所有元素生效。

邊框

CALayer通過borderWidthborderColor兩個屬性的組合來定義border的寬度和顏色

陰影

通過設(shè)置shadowOpacity屬性為一個大于0的值,可以給任意layer添加一個背景陰影。取值范圍是0.0到1.0,表示全透明到非透明。同時還可以通過shadowColor(默認為黑)、shadowOffset(距離和方向)和shadowRadius(模糊度)三個屬性來修改陰影的外觀。不同于border圍繞在layer的bounds,shadow是圍繞在真正的內(nèi)容外的??梢远xshadowPath來自定義陰影路徑

遮罩(Masking)

mask屬性接受另外一個CALayer值,可以被用作將當前l(fā)ayer裁切成給定layer的輪廓。masksToBounds則是讓子視圖不超過父視圖的范圍

Opacity

這里要說得是當子圖層和父圖層都設(shè)置了Opacity的時候(比如父類為0.5,子類為0.5 ,那么實際上子類的透明度為0.5*0.5+0.5(父類)=0.75).而下面是你設(shè)置透明度和alpha等需要注意的
1.opaque 直接不再繪制這層layer下面的layer(效率高)
2.alpha會影響在layer上視圖的透明度

  1. 在app的Info.plist中添加UIViewGroupOpacity=YES。這會作用于當前app下的所有范圍,可能還有點小的性能浪費。
  2. 通過CALayershouldRasterize=YES,將layer及其子layer全部打散成一個平面的圖形,再使Opacity生效就可以達到我們想要的效果了。由于rasterizationScale默認等于1.0,會使得高清屏幕下圖片像素化,所以我們還要同時設(shè)置一下:layer.rasterizationScale = UIScreen.mainScreen().scale

Transforms

UIViewtransform屬性類型是GAffineTransform,它用于對view進行二維空間下的旋轉(zhuǎn)、拉伸或變形。其實他就是對CALayer的封裝。CALayer同時也有一個transform屬性,它的類型是CATransform3DCATransform3D是一個4x4的矩陣,從而支持了對于垂直屏幕的z軸的變換效果。其中m34屬性通常被用來計算x和y值的縮放比例,默認值是0)。CALayer實現(xiàn)仿射變化的屬性是affineTransform(UIView就是對這個的封裝)。CATransform3D的定義和它各個參數(shù)的作用如下。

struct CATransform3D {
  m11(x縮放), m12(y切變),m13(旋轉(zhuǎn)),  m14();
  m21(x切變), m22(y縮放), m23(),    m24();
   m31(旋轉(zhuǎn)),  m32( ),    m33(), 
 m34(透視效果,要操作的這個對象要有旋轉(zhuǎn)的角度,否則沒有效果。正直/負值都有意義)
 m41(x平移),     m42(y平移),     m43(z平移),     m44();
 };

CATransform3D相關(guān)的函數(shù)

CATransform3D CATransform3DTranslate (CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz);
t:就可以理解為:函數(shù)的疊加,效果的疊加。
CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
sx:X軸縮放,代表一個縮放比例,一般都是 0 --- 1 之間的數(shù)字。sy:Y軸縮放。
sz:整體比例變換時,也就是m11(sx)== m22(sy)時,若m33(sz)>1,圖形整體縮小,若0<1,圖形整體放大,若m33(sz)<0,發(fā)生關(guān)于原點的對稱等比變換。
CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x, CGFloat y, CGFloat z);
旋轉(zhuǎn)效果。angle:旋轉(zhuǎn)的弧度,所以要把角度轉(zhuǎn)換成弧度:角度 * M_PI / 180。
x:向X軸方向旋轉(zhuǎn)。值范圍-1 --- 1之間y:向Y軸方向旋轉(zhuǎn)。值范圍-1 --- 1之間
z:向Z軸方向旋轉(zhuǎn)。值范圍-1 --- 1之間

CALayer的子類

CAGradientLayer

實現(xiàn)CALayer的漸變色

 // 漸變圖層
    let gradientL = CAGradientLayer()
    gradientL.frame = bottomView.bounds;
    gradientL.opacity = 0;
    gradientL.colors = @[UIColor.clearColor().CGColor,UIColor blackColor().CGColor];

CAReplicatorLayer

CAReplicatorLayer復(fù)制圖層,把子圖層放在CAReplicatorLayer中,,可以把圖層里面所有子層復(fù)制.這個圖層用于,有許多相同的子視圖做相同的動畫效果的時候,這個可以復(fù)制這些子視圖,并且為這些子視圖加上延遲等效果

  let repL = CAReplicatorLayer()
  repL.frame = _lightView.bounds;
  _lightView.layer.addSublayer(repL)
  // 子圖層
  let layer = CALayer()
  layer.anchorPoint = CGPointMake(0.5, 1)
  layer.position = CGPointMake(15, _lightView.bounds.size.height)
  layer.bounds = CGRectMake(0, 0, 30, 150)
  repL.addSublayer(layer)
  let anim = CABasicAnimation()
  anim.keyPath = "transform.scale.y"
  anim.toValue = 0.1
  anim.duration = 0.5
  anim.repeatCount = MAXFLOAT;
  // 設(shè)置動畫反轉(zhuǎn)
  anim.autoreverses = YES;
  layer.addAnimation(anim,forKey:nil)
  // 復(fù)制層中子層總數(shù)
  // instanceCount:表示復(fù)制層里面有多少個子層,包括原始層
  repL.instanceCount = 3;
  // 設(shè)置復(fù)制子層偏移量,不包括原始層,相對于原始層x偏移,instanceTransform決定如何排序
  repL.instanceTransform = CATransform3DMakeTranslation(45, 0, 0);
  // 設(shè)置復(fù)制層動畫延遲時間
  repL.instanceDelay = 0.1;
  // 如果設(shè)置了原始層背景色,就不需要設(shè)置這個屬性
  repL.instanceColor = UIColor.greenColor().CGColor
  repL.instanceGreenOffset = -0.3;

UIView和CALayer的選擇

其實,對比CALayerUIView多了一個事件處理的功能。也就是說,CALayer不能處理用戶的觸摸事件,而UIView可以.所以,如果顯示出來的東西需要跟用戶進行交互的話,用UIView;如果不需要跟用戶進行交互,用UIView或者CALayer都可以當然,CALayer的性能會高一些,因為它少了事件處理的功能,更加輕量級。雖然CALayer不感知responder chain,但是他通過提供-containPoint:-hitTest:兩個方法來幫助你定位事件所在layer。
我們?yōu)槭裁匆私?code>CALayer的存在,因為他有一些UIView不能做的事情:

  1. 陰影、圓角、多彩的border
  2. 3D變化和定位
  3. 非矩形的邊界
  4. alpha遮罩
  5. 多步非線性動畫

layer的繪制

在UIView的子類中可以通過實現(xiàn)-drawRect:方法來自定義繪圖,CALayer的自定義繪圖則通過layer的delegate對象(CALayerDelegate 協(xié)議)的以下兩個方法來實現(xiàn):

     // 方法1 需要手動調(diào)用layer.display()方法來調(diào)用
             func displayLayer(_ layer: CALayer!);

    // 方法2. 如果方法1沒有實現(xiàn),則調(diào)方法2。需要手動調(diào)用layer.display()方法來調(diào)用
  func drawLayer(_ layer: CALayer!, inContext  ctx,:  CGContext )

layer tree

CoreAnimation是一個合成引擎,它的工作是盡可能快的將不同的可視化的內(nèi)容合成到屏幕上。這個可視化內(nèi)容是不同的層(layer),構(gòu)成一個叫做層樹(layer tree)的層次結(jié)構(gòu)。層樹主要由三個部分組成:

layer tree.png
  1. 模型層樹:app交互的地方,存儲目標值的地方
  2. 外觀層樹:展示值得地方(從origin到target),在這一層獲取動畫過程中的當前值,這一層通過presentationLayer()方法獲取。這層就是所看到的動畫,但是實際上控件上的視圖的frame之類的屬性沒有發(fā)生變化。
  3. 渲染層樹:私有的方法

隱式動畫

每一個UIView內(nèi)部都默認關(guān)聯(lián)著一個CALayer,我們可用稱這個Layer為Root Layer(根層)。所有的非Root Layer(也就是手動創(chuàng)建的CALayer對象),都存在著隱式動畫,也就是說當對非Root Layer的部分屬性進行修改時,默認會自動產(chǎn)生一些動畫效果而這些屬性稱為Animatable Properties(可動畫屬性)常見的Animatable Properties:

  1. bounds:用于設(shè)置CALayer的寬度和高度。修改這個屬性會產(chǎn)生縮放動畫
  2. backgroundColor:用于設(shè)置CALayer的背景色。修改這個屬性會產(chǎn)生背景色的漸變動畫
  3. position:用于設(shè)置CALayer的位置。修改這個屬性會產(chǎn)生平移動畫

當然這個隱式的動畫可以通過動畫事務(wù)(CATransaction)關(guān)閉,它負責(zé)成批的把多個圖層樹的修改作為一個原子更新到渲染樹。

核心動畫

核心動畫繼承結(jié)構(gòu)

核心動畫的繼承關(guān)系如下

屏幕快照 2016-06-26 01.12.04.png

從上圖中可以看到核心動畫中所有類都遵守CAMediaTiming。CAAnaimation是所有動畫類的父類,是個抽象類,不具備動畫效果.CAAnimationGroupCATransition才有動畫效果,CAAnimationGroup是個動畫組,可以同時進行縮放,旋轉(zhuǎn)。CATransition是轉(zhuǎn)場動畫,界面之間跳轉(zhuǎn)都可以用轉(zhuǎn)場動畫。CAPropertyAnimation也是個抽象類,本身不具備動畫效果,只有子類才有.CABasicAnimation基本動畫,做一些簡單效果CAKeyframeAnimation幀動畫,做一些連續(xù)的流暢的動畫.給一個圖層添加動畫的步驟為如下

  1. 創(chuàng)建CALayer
  2. 初始化一個CAAnimation對象,并設(shè)置一些動畫相關(guān)屬性
  3. 通過調(diào)用CALayeraddAnimation:forKey:方法,增加CAAnimation對象到CALayer中,這樣就能開始執(zhí)行動畫了
  4. 通過調(diào)用CALayerremoveAnimationForKey:方法可以停止CALayer中的動畫

CAAnimation的屬性介紹

CAAnimation是所有動畫對象的父類,負責(zé)控制動畫的持續(xù)時間和速度,是個抽象類,不能直接使用.下面需要對它的一些屬性的介紹

CAMediaTiming協(xié)議的屬性

  1. duration:動畫的持續(xù)時間
  2. repeatCount:重復(fù)次數(shù),無限循環(huán)可以設(shè)置HUGE_VALF或者MAXFLOAT
  3. repeatDuration:重復(fù)時間
  4. fillMode:決定當前對象在非active時間段的行為。比如動畫開始之前或者動畫結(jié)束之后. 因為動畫是在presenting tree上展現(xiàn)的,動畫結(jié)束后是展現(xiàn)的模型樹,presenting tree將被移除。
  5. beginTime:可以用來設(shè)置動畫延遲執(zhí)行時間,若想延遲2s,就設(shè)置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當前時間

CAAnimation的屬性

  1. removedOnCompletion:默認為YES,代表動畫執(zhí)行完畢后就從圖層上移除,圖形會恢復(fù)到動畫執(zhí)行前的狀態(tài)。如果想讓圖層保持顯示動畫執(zhí)行后的狀態(tài),那就設(shè)置為NO,不過還要設(shè)置fillMode為kCAFillModeForwards
  2. timingFunction:速度控制函數(shù),控制動畫運行的節(jié)奏如:kCAMediaTimingFunctionLinear等
  3. delegate:動畫代理(CAAnimationDelegate)代理方法監(jiān)聽動畫的開始結(jié)束等狀態(tài)

CABasicAnimation

隨著動畫的進行,在長度為duration的持續(xù)時間內(nèi),keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)?code>toValue.keyPath內(nèi)容是CALayer的可動畫Animatable屬性如果fillMode=kCAFillModeForwardsremovedOnComletion=false,那么在動畫執(zhí)行完畢后,圖層會保持顯示動畫執(zhí)行后的狀態(tài)。但在實質(zhì)上,圖層的屬性值還是動畫執(zhí)行前的初始值,并沒有真正被改變。(只是沒有移除掉presenting tree)

**注意:核心動畫一切都是假象,并不會真實的改變圖層的屬性值,如果以后做動畫的時候,不需要與用戶交互,通常用核心動畫(轉(zhuǎn)場)。UIView動畫必須通過修改屬性的真實值,才有動畫效果。
**

CAKeyframeAnimation

CAKeyframeAnimation會使用一個NSArray保存動畫的屬性數(shù)值

  1. values:上述的NSArray對象。里面的元素稱為“關(guān)鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內(nèi),依次顯示values數(shù)組中的每一個關(guān)鍵幀
  2. path:可以設(shè)置一個CGPathRef、CGMutablePathRef,讓圖層按照路徑軌跡移動。path只對CALayeranchorPointposition起作用。如果設(shè)置了path,那么values將被忽略
  3. keyTimes:可以為對應(yīng)的關(guān)鍵幀指定對應(yīng)的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應(yīng)values中的每一幀。如果沒有設(shè)置keyTimes,各個關(guān)鍵幀的時間是平分的

CAAnimationGroup

CAAnimationGroup可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時并發(fā)運行,主要的屬性有

  1. animations:用來保存一組動畫對象的Array默認情況下,一組動畫對象是同時運行的,也可以通過設(shè)置動畫對象的beginTime屬性來更改動畫的開始時間

CATransition

CATransition用于做轉(zhuǎn)場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。UINavigationController就是通過CATransition實現(xiàn)了將控制器的視圖推入屏幕的動畫效果.主要的動畫屬性有:

  1. type:動畫過渡類型
  2. subtype:動畫過渡方向
  3. startProgress:動畫起點(在整體動畫的百分比)
  4. endProgress:動畫終點(在整體動畫的百分比)

type屬性控制著轉(zhuǎn)場動畫過渡效果

轉(zhuǎn)場動畫過渡效果

可以通過

+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

實現(xiàn)單視圖的轉(zhuǎn)場,而兩個視圖則得通過下面的方法

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion

定時器

當你需要定時的執(zhí)行同一個效果的動畫的時候,就需要使用定時器,iOS中有兩種定時器,NSTimerCADisplayLink。NSTimer就是普通意義上的定時器,下面主要是講CADisplayLink

CADisplayLink

CADisplayLink是一種以屏幕刷新頻率觸發(fā)的時鐘機制,每秒鐘執(zhí)行大約60次左右,可以使繪圖代碼與視圖的刷新頻率保持同步,而NSTimer無法確保計時器實際被觸發(fā)的準確時間,一個CADisplayLink實例對象,會根據(jù)更新率定時同步繪畫內(nèi)容。需要提供一個選擇器,當更新內(nèi)容的時候。這個需要添加到一個RunLoop當中的去(相當是添加了定時器類型的Runloop)。
具體的使用使用方法:

  1. 定義CADisplayLink并制定觸發(fā)調(diào)用方法
  2. 將顯示鏈接添加到主運行循環(huán)隊列

CADisplayLink相關(guān)的屬性有

  1. duration:每幀之間的時間
  2. frameInterval:就是間隔多少幀調(diào)用一次選擇器。,默認值是1.
  3. paused: 是否暫停當前的定時器,控制 CADisplayLink的運行
  4. timestamp:上一幀結(jié)束時候的時間,下一幀需要知道什么內(nèi)容將被呈現(xiàn)

由于 CADisplayLink 綁定的方法會在每次屏幕刷新時被調(diào)用,精確度相當之高。正是基于這個特點,CADisplayLink 非常適合 UI 的重繪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容