CoreAnimation:
Core Animation自身并不是一個繪圖系統。它只是一個負責在硬件上合成和操縱應用內容的基礎構件。Core Animation的核心是圖層對象,圖層對象用于管理和操控你的應用內容。圖層將捕獲的內容放到一副位圖中,圖形硬件能夠非常容易的操控你的位圖。在大部分應用中,圖層被作為一種管理視圖內容的方式,但是你也可以創建標準的圖層,這取決于你自身的需要。
動畫類結構:
補充一下,CABasicAnimation還有子類CASpringAnimation,彈簧動畫。屬性動畫貴在屬性,CALayer的屬性,對應于不同的CALayer,可以針對其屬性設置變化,如CAShaperLayer,可以設置strokeEnd屬性,做出畫筆畫圖的效果。
隱式動畫:
從舊屬性值動畫到新屬性值的動畫形式。系統自動補全對象從當前形態到目標形態變化過程的行為。隱式是因為我們并沒有指定任何動畫的類型。我們僅僅改變了一個屬性,然后Core Animation來決定如何并且何時去做動畫。例如給某屬性賦新值
圖層定義和給圖層提供內容
圖層是管理app內容的數據對象。圖層的內容由包含可視數據的位圖構成。使用下述三種方式之一可給提供圖層的內容:
- 直接賦值一個UIImage對象給圖層對象contents屬性。(這個技術適用于圖層內容從不或幾乎不改變的情形。)
- 賦值一個代理給圖層,由代理負責繪制圖層內容。(該技術適用于圖層內容可能偶爾改變,且內容可由外部對象提供,比如視圖。)
- 定義一個CALayer的子類并覆蓋類的繪圖方法,有覆蓋的方法返回圖層的內容。(該技術適用于你需要創建自定義圖層的子類,或者你想改變圖層基本的繪圖行為。)
圖層的種類:
類別 | 用途 |
---|---|
CAShaperLayer | 用于繪制三次貝塞爾曲線。CAShaperLayer對繪制基于路徑的形狀非常有幫助。因為CAShaperLayer總是生成一個最新的路徑。而如果將路徑畫在圖層儲備中,一旦圖層被縮放,形狀就變形了。 |
CATransformLayer | 用于渲染一個真3D的圖層層級。而不是由其他圖層類實現的2D圖層層級。 |
CAEmitterLayer | 用于實現基于Core Animation粒子發射系統。發射器層對象控制粒子的生成和起源 |
CAGradientLayer | 用于繪制一個顏色漸變填充圖層的形狀(所有圓角矩形邊界內的部分) |
CAEAGLLayer/CAOpenGLLayer | 用于設置需要使用OpenGL ES(iOS)或OpenGL(OS X)繪制的內容與內容儲備。 |
CAReplicatorLayer | 當你想自動生成一個或多個子層的拷貝。復制器為你生成拷貝并使用你指定的屬性值以修改復制品的外觀和屬性。 |
CAScrollLayer | 用于管理由多個子區域組成的大的可滾動區域 |
CATextLayer | 用于渲染一個無格式或屬性文本字符 |
QCCompositionLayer | 用于渲染一個Quartz組件元素(僅在OS X中有效) |
圖層和視圖相關:
1.圖層對象是組織在三維空間的二維平面。它是使用Core Animation執行任何操作的核心構件。和視圖一樣,圖層的可管理信息包括幾何結構、內容、可視屬性;與視圖不同的是,圖層沒有定義它自己的外觀,圖層僅管理周圍位圖的狀態信息。
2.基于圖層的繪圖和基于視圖的繪圖在技術上有明顯的不同。<font color = red>對基于視圖的繪圖,對視圖的改變經常會觸發調用視圖的drawRect:方法以重繪視圖內容。但是此種方式的代價相對較高,因為它是CPU在主線程上的操作。Core Animation通過盡可能的使用圖形硬件操縱緩存后的位圖來避免了這種開銷,從而完成相同或相似的效果。</font>
3.大部分圖層<font color = red>不做實際的繪圖操作</font>。相反,圖層捕獲應用的內容并緩存它們到位圖中。位圖有時也被稱為儲備(backing store)。當你隨后改變了一個圖層的屬性值,你做的所有工作只是改變了與圖層對象相關聯的狀態信息。當你的更改觸發了一個動畫,Core Animation會將該圖層對應的位圖數據和圖層的狀態信息發送給圖形處理硬件。
4.圖層不是視圖的替代品。因此無法創建一個基于單一圖層對象的可視界面。圖層是視圖的基礎設施。具體地,圖層讓視圖的繪圖和動畫更簡單和高效,并且能在繪圖和動畫時保持高幀率。然而許多事情圖層無法做到。圖層不能處理事件、繪制內容,特別是在響應鏈中,或是做一些其他的事情。因此,每個app必須有一個或多個視圖來處理這類交互。
自定義圖層創建相關
圖層創建相關,主要有以下幾種方式:
- 直接創建CALayer的子類,重寫drawInContext方法
- 創建UIView,在drawRect方法中,通過獲取上下文,繪制需要的內容,添加到當前view的Layer上,獲取上下文,其實就是獲取對應view的Layer
- 創建圖層,通過delegate回調方法-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx,動態創建繪制內容。
以上是3種創建自定義圖層的方法,補充說明下:
(1)無論采取哪種方法來自定義層,都必須調用CALayer的setNeedsDisplay方法才能正常繪圖。
(2)詳細現實過程:當UIView需要顯示時,它內部的層會準備好一個CGContextRef(圖形上下文),然后調用delegate(這里就是UIView)的drawLayer:inContext:方法,并且傳入已經準備好的CGContextRef對象。而UIView在drawLayer:inContext:方法中又會調用自己的drawRect:方法。平時在drawRect:中通過UIGraphicsGetCurrentContext()獲取的就是由層傳入的CGContextRef對象,在drawRect:中完成的所有繪圖都會填入層的CGContextRef中,然后被拷貝至屏幕。
注意:不能再將某個UIView設置為CALayer的delegate,因為UIView對象已經是它內部根層的delegate,再次設置為其他層的delegate就會出問題。在設置代理的時候,它并不要求我們遵守協議,說明這個方法是nsobject中的,就不需要再額外的顯示遵守協議了。
圖層樹:
使用Core Animation的app擁有三個圖層對象集合。每一個圖層對象集合在呈現app內容上都扮演著不同的角色。
<font color = #0099ff>模型圖層樹</font>中的對象(或簡稱“圖層樹”)用的最多。在這個樹中的對象是模型對象,模型對象負責存儲所有動畫的目標值。無論何時改變圖層的屬性值,你使用的始終是某一個模型對象。
<font color = #0099ff>呈現樹</font>中的對象包含所有運行中的動畫的瞬時值。圖層樹對象包含的是動畫的目標值,而呈現樹中的對象代表顯示在屏幕上動畫的當前值。你不應該更改這個樹中的對象。相反,你使用這些對象來讀取當前動畫的值,可能用于創建開始于這些值的新的動畫。
在<font color = #0099ff>渲染樹</font>中的對象執行實際的動畫,并且對Core Animation是不公開的。
contentGravity屬性:
當給圖層的contents屬性賦值一個圖片,圖層的contentsGravity屬性確定圖片如何適合當前的邊界。默認情況下,如果一個圖片大于小于當前的邊界,圖層對象縮放圖片以適應有效的空間。如果圖層的長寬比和圖片的長寬比不一致,這會導致圖片被扭曲。所以你可以使用contentsGravity屬性來確定你的內容以最佳的方式被呈現。
你可以向contentsGravity屬性賦予的值分為兩個分類:
1.基于位置的引力約束允許你固定你的圖片到圖層矩形邊界的一個特殊的邊緣或角落,不會縮放圖片。
2.基于縮放的引力約束允許你伸縮圖片使用多個選項之一,某些選項保留長寬比,有些則不保留。
使用高分辨率圖片:
圖層并不知道當前設備的分辨率信息。圖層只是簡單的存儲一個指向位圖的指針,并用給定的有效像素以最佳的方式顯示。如果你賦值一個圖片給圖層的contents屬性,你必須給圖層的contentsScale屬性設置一個正確的值以告訴Core Animation關于圖片的分辨率。默認的屬性值為1.0,對于在標準分辨率的屏幕上顯示圖片是正確的。如果你的圖片要在Retina屏幕上顯示,該值需要設定為2.0。使用[[UIScreen mainScreen] scale]可獲取正確的縮放率。
圖層的可視樣式和外觀:
圖層對象擁有內建的可視裝飾,如邊框、背景色。你可以使用這些裝飾對圖層的主內容進行補充。<font color = red>因為這些可視的裝飾不需要任何渲染。</font>裝飾讓圖層在一些情況下讓圖層成為獨立的實體成為可能。你只需設置圖層的屬性,圖層自會處理必要的繪圖工作,包括動畫。
注意:你可以將圖層的背景設置成任何顏色,包括支持透明的顏色或使用模式(pattern)圖片。使用模式圖片時,渲染是由Core Graphics完成,它使用的是標準坐標系統。標準坐標系統和iOS的坐標系統是不一樣的。所以,圖片在iOS上得渲染結果是顛倒的。可以使用[backgroundLayer setTransform:CATransform3DMakeScale(1.0, -1.0, 1.0)];解決該問題。
如果你將圖層的背景顏色設置為不透明。考慮將圖層的opaque屬性設置為YES。當合成屏幕上的圖層時可以提升系能,圖層的后備存儲也不需管理alpha通道。如果你給圖層設置了非零的圓角半徑,則不可以將圖層標記為不透明類型。
顯式動畫的方式呈現圖層屬性的變化:
CABasicAnimation* fadeAnimation = [CABasicAnimation animationWithKeyPath:@”opacity”;
fadeAnimation.fromValue = [NSNumber numberWithFloat:1.0];
fadeAnimation.toValue = [NSNumber numberWithFloat:0.0];
fadeAnimation.duration = 1.0;
[theLayer addAnimation:fadeAnimation forKey:nil];
//改變圖層實際的最后數據值
theLayer.opacity = 0.0; // 記得更新圖層樹
注意:創建一個顯示動畫,推薦是賦值一個值給動畫對象的fromValue屬性。如果你沒有為該屬性指定值,Core Animation將使用圖層的當前值作為開始值。如果已經更新了屬性作為它的最終值,這將致使fromValue屬性值遭到干擾,結果可能并不是你想要的。
不同于隱式動畫,隱式動畫會更新圖層對象的值。而顯示動畫不會更改圖層樹中的數據。<font color = red>顯示動畫僅是創建了一個動畫。在動畫結束之后,Core Animation從圖層中移除該動畫對象并使用當前的數據值重繪圖層。</font>如果你想讓顯示動畫的改變成為永久性的,如你在之前的例子中看到的,你必須更新圖層屬性。
隱式和顯示動畫都會在當前運行循環周期結束之后開始執行,并且當前的線程必須擁有一個用于執行動畫的運行循環runloop。如果你改變了圖層的動畫屬性或者給圖層添加了多個動畫對象。所有這些動畫將會同時被執行。例如將圖層移動到屏幕之外的時候添加漸隱動畫,這兩個動畫是同時運行的。然而你可以讓動畫對象在一個特殊的時間開始執行。
CalculationMode屬性:
線性和曲線動畫,動畫的calculationMode屬性被設置為kCAAnimationLinear或CAAnimationCubic,屬性值被用于提供定時器信息以生成動畫。這些模式值讓你最大化控制動畫的定時器。
節奏動畫,動畫的calculationMode屬性被設置為kCAAnimationPaced或kCAAnimationCubicPaced,這些屬性值不依賴由keyTimes或timingFunctions屬性提供的額外定時器值。相反,定時器值被隱式地計算以提供一個常速率動畫。
離散動畫,動畫的calculationMode屬性被設置為kCAAnimationDiscrete,該值將引起動畫屬性從一個關鍵幀跳到另一個沒有任何補間動畫的下一個關鍵幀。計算模式使用keyTimes屬性值,但忽略timingFunctions屬性。
<font color = red>keyTimes</font>屬性為應用在每一關鍵幀指定應用到每一個關鍵幀上的計時器。該屬性只在calculationMode屬性被設置為kCAAnimationLinear,kCAAnimaitonDiscrete,kCAAnimationCubic時被使用。它不使用在節奏動畫中。
<font color = red>timingFunctions</font>屬性指定使用在每一個關鍵幀部分的定時曲線(該屬性替換了繼承的timingFunction屬性)。
同時動畫多個屬性變化:
// Animation 1
CAKeyframeAnimation* widthAnim = [CAKeyframeAnimation animationWithKeyPath:@"borderWidth"];
NSArray* widthValues = [NSArray arrayWithObjects:@1.0, @10.0, @5.0, @30.0, @0.5,@15.0, @2.0, @50.0, @0.0, nil];
widthAnim.values = widthValues;
widthAnim.calculationMode = kCAAnimationPaced;
// Animation 2
CAKeyframeAnimation* colorAnim = [CAKeyframeAnimation animationWithKeyPath:@"borderColor"];
NSArray*colorValues=[NSArray arrayWithObjects:(id)[UIColorgreenColor].CGColor,(id)[UIColorredColor].CGColor,(id)[UIColorblueColor].CGColor, nil];
colorAnim.values = colorValues;
colorAnim.calculationMode = kCAAnimationPaced
// Animation group
CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:colorAnim, widthAnim, nil];
group.duration = 5.0;
[myLayer addAnimation:group forKey:@"BorderChanges"];
對于分組動畫的更高級的方式是使用一個 <font color = red> 事務對象</font>。事務提供了更加靈活的方式,允許你創建內嵌的動畫集合以及給每一個動畫賦值不同的動畫參數。
檢測動畫結束:
Core Animaiton提供對動畫開始與結束的檢測支持。這些通知是執行所有與動畫相關的內務處理的最佳時刻。比如說你可能使用開始通知設置一些相關狀態信息,使用對應的結束通知清理這些狀態。
有兩種不同的方式獲取關于動畫狀態的通知:
- 使用setCompletionBlock:方法添加一個完成塊給當前的事務。當事務中的所有動畫完成后,事務將執行你的完成塊。
- 給CAAnimaiton對象賦值一個代理,該代理實現了animationDidStart:方法和animaitonDidStop:finished:代理方法。
如果你想將兩個動畫鏈接在一起,使得當第一個動畫結束之后啟動第二個動畫。不要使用動畫通知。相反,使用動畫對象的beginTime屬性在希望的時間啟動動畫。為了將兩個動畫鏈接在一起,設置第二個動畫的開始時間為第一個動畫的結束時間。
圖層、視圖和動畫
- 原則:如果一個圖層屬于一個圖層支持視圖,創建動畫的推薦做法是使用由UIKit或AppKit提供的基于視圖的動畫接口。有幾種使用Core Animation接口直接動畫圖層的方式,但如何創建這些動畫依賴于目標平臺。
- 視圖的動畫:UIView類默認是關閉圖層動畫的,但在動畫塊中重新啟用圖層動畫。如果想使用Core Animation初始化動畫,你必須在一個基于視圖的動畫塊內部執行所有Core Animaiton調用。
[UIView animateWithDuration:1.0 animations:^{
// Change the opacity implicitly.
myView.layer.opacity = 0.0;
// Change the position explicitly.
CABasicAnimation* theAnim=[CABasicAnimation animationWithKeyPath:@"position"];
theAnim.fromValue = [NSValue valueWithCGPoint:myView.layer.position];
theAnim.toValue = [NSValue valueWithCGPoint:myNewPosition];
theAnim.duration = 3.0;
[myView.layer addAnimation:theAnim forKey:@"AnimateFrame"];
}];
約束與動畫:如果你使用基于約束的布局規則管理你的視圖位置,你必須移除任何可能對動畫的配置部分造成干擾的約束。約束將影響所有你對視圖的位置和尺寸的改變。也會影響到視圖和它的子視圖的關系。如果你正在動畫改變所有這些項目,你可以移除這些約束后再做改變,接著應用需要的新約束。
圖層層級:大多數時候,使用圖層的最佳方式是將圖層和視圖配合使用。可能你需要向視圖添加另外的圖層對象以增加視圖層級。為了獲得更佳的性能或者單獨使用視圖實現你需要的功能會比較困難時而選擇使用圖層。圖層層級在許多方式上都與視圖的層級相似。嵌入一個圖層到另一個圖層中,嵌入的圖層(稱為sublayer)與父圖層(稱為superlayer)之間將形成一個父子關系。
圖層操作:
行為 | 方法 | 描述 |
---|---|---|
添加圖層 | addSublayer: | 給當前的圖層添加一個新的子層對象。子層被加入到當前圖層的子層列表的末尾。圖層將顯示在所有與其有相同zPosition屬性值的同胞圖層的頂部。 |
插入圖層 | insertSublayer:above:insertSublayer:atIndex:insertSublay:below: | 將子圖層插入到子圖層層次中指定的索引或者相對于其他子圖層的位置。當插入到其他圖層的上方或下方,你僅需指定子圖層在子圖層數組中的位置。圖層的可視性主要由它的zPosition屬性決定,然后是由其在子圖層數組中的位置決定。 |
移除圖層 | removeFromSuperlayer | 將子圖層從父圖層中移除 |
交換圖層 | replaceSublayer:with | 將某個子圖層與另外的圖層交換位置。如果你插入的圖層已經在另外的圖層層次中,首先它將從圖層之前的圖層層次中移除 |
注意:以上方法,不能管理屬于layer-backed視圖的圖層。然而一個layer-backed視圖可以作為你創建的獨立圖層的父圖層。
- 子圖層的位置和尺寸:當添加和插入一個子圖層,在它顯示到屏幕之前你必須設置子圖層的尺寸和位置。你可以在子圖層被添加到圖層層次之后更改其位置與尺寸,但應該養成在創建圖層的時候就設置這些值的習慣。<font color = red>重要:圖層寬和高總是設置整型數</font>。
子圖層與剪裁:一個父圖層不會自動地裁剪超出其邊界的子圖層的內容。相反,默認情況下,父圖層允許他的子圖層完全的被顯示。然而,通過設置圖層的masksToBounds屬性為YES,你可以重新啟用裁減功能。
如果圓角半徑被指定的話,一個圖層的裁減蒙版形狀包括圖層的圓角半徑。下圖說明了masksToBounds屬性如何影響一個擁有圓角半徑的圖層。當masksToBounds屬性被設置為NO,整個子圖層被顯示,盡管它已經超出了它的父圖層的邊界。將masksToBounds屬性設為YES,將引起超出父圖層的子圖層內容被裁減掉。此時使用陰影,則在圖片范圍內部的陰影會被保留,外部的會被裁剪掉,當圖片背景中空透明時明顯。合適的做法是在圖層下面插入一個等大的圖層,用于設置陰影。
過渡動畫相關:一個過渡動畫對象為圖層創建一個可動畫的可視過渡。最普遍的過渡對象用法是動畫一個圖層的顯現和消失。與基于屬性的動畫不同,一個過渡動畫操縱一個<font color = red>圖層的緩存圖片</font>以創建可視效果,如果通過單獨的改變屬性實現會非常的困難,也許根本無法實現。
myView1和myView2被放置在相同父視圖中的相同位置,但只有myView1是當前可視的。推入過渡引起myView1一邊漸隱一邊向左滑出,直到它被隱藏,而myView2從右側滑入變成可視。更新兩個視圖的隱藏屬性確保兩個視圖的可視性在動畫的結尾是正確的。對一個圖層應用推入過渡,第一個滑出的圖層的使用當前的可視性,而右側滑入的圖層使用最后修改后的可視性。
CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
transition.duration = 0.5;
// 為兩個圖層加入過渡動畫
[_myView1.layer addAnimation:transition forKey:@"transition"];
[_myView2.layer addAnimation:transition forKey:@"transition"];
// 最后,改變圖層的可視性
_myView1.hidden = !_myView1.hidden;
_myView2.hidden = !_myView2.hidden;
當兩個圖層包含相同的過渡特效,你可以對兩個圖層應用同一個過渡對象。使用相同的過渡對象也簡化了代碼。然而,你也可以使用不同的過渡對象并且如果對每個圖層過渡參數都是不同的,那么就肯定需要使用兩個不同的過渡對象。
fillMode 選項含義:
kCAFillModeForwards:當動畫結束后,layer會一直保持著動畫最后的狀態.
kCAFillModeBackwards:在動畫開始前,你只要將動畫加入了一個layer,layer便立即進入動畫的初始狀態并等待動畫開始. 你可以這樣設定測試代碼,將一個動畫加入一個layer的時候延遲5秒執行.然后就會發現在動畫沒有開始的時候,只要動畫被加入了layer,layer便處于動畫初始狀態。反之,layer會跳一次最終值,然后再開始動畫。
both 是上面兩者都有,remove則是當動畫開始前和動畫結束后,動畫對layer都沒有影響,動畫結束后,layer會恢復到之前的狀態
暫停與恢復動畫:為了暫停一個動畫,你可以利用圖層適配CAMediaTiming協議這一點,設置圖層動畫的速度為0.0.設置速度為0暫停動畫直到你改變該屬性值為一個非零值。清單5-4展示了一個簡單的關于如何暫停和恢復動畫的例子。
-(void)pauseLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime()
fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime()
fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
顯示事務:使用CATransaction類提供的方法創建與管理事務。通過調用begin類方法,可以開始(或隱式地創建)一個新的事務;調用commit類方法可結束一個事務。兩個方法之間的代碼就是作為事務部分的變化。顯示事務可以作用隱式動畫。
[CATransaction begin];
theLayer.zPosition = 200.0;
theLayer.opacity = 0.0;
[CATransition commit];
提示動畫性能相關:
- 盡可能使用不透明圖層:設置opaque屬性為YES可以讓核心動畫知道不需要給圖層維持alpha通道,沒有alpha通道意味著就不需要渲染這層的背景內容了,從而節省了渲染時間。然后這個屬性主要是用于設置層或者以層為基礎的視圖的,也或者是用于核心動畫創造的底層bitmap層的情況。如果把一張圖像直接設置為層的contents屬性,那么這個圖像的alpha通道會被強制保留,無論你設不設定這個值。
- 將復雜路徑拆分成簡單路徑:CAShapeLayer類根據你提供的路徑來渲染到bitmap圖像,在合成的時候渲染成內容。這么做的優點是層總是在最佳分辨率繪制路徑,但是這個優點會消耗額外的渲染時間。如果這個路徑太復雜,渲染的代價就會很高,并且如果這個路徑的尺寸經常改變(這會導致重繪也經常發生),用于繪畫的時間也會增加,這會成為一個阻止最佳表現性能的瓶頸。
- 顯式為相同的圖層設置contents屬性:如果你在多個層對象上使用同一張圖片,自己加載圖像,把這個圖像直接分派給這些層對象的contents屬性。分配一個圖像到contents屬性可以預防分配用于內容儲備的內存空間(UIView實際并不將自己繪制到屏幕上,而是先繪制到它的圖層上,然后是圖層顯示在屏幕上,視圖并不會頻繁的重繪;相反,它的繪圖結果會被緩存起來,而繪圖的緩存版本(后備存儲)將被用到適當的地方)。反而這個層用你提供的圖像當做后備存儲。當幾個層用同樣的圖片,那么這些層就在共享一份內存而不是為自己再分配一個圖片拷貝。
- 總是將圖層的尺寸設置為整數值:為了最好的效果,應該將層對象的寬和高設置為整數值,雖然你使用浮點數的形式設定圖層邊界的寬高,圖層的邊界最終用于創建一個bitmap圖片。指定圖層的寬高為整型值會簡化Core Animation必要的創建和管理備份存儲與其他圖層信息的工作。
- 當給圖層添加一個陰影指定一個陰影路徑:讓Core Animation自己決定陰影的形狀是個大的開銷且影響app的表現。相比讓它自己決定,應該用shadowPath屬性明確地指定一個陰影形狀。當你這么干的時候,核心動畫用這個形狀去繪制和緩存陰影特效。對那些從不改變或者很少改變形狀的層,這是一個很好的效果提升通過減少渲染數量。
視圖動畫和核心動畫一些需要注意的點:
[UIView animate]的方法里只能對UIView的屬性進行動畫,對于layer的屬性是無效的。比如你在這里想讓self.AnimateView.layer.cornerRadius = 50.0; 是沒有意義的。必須使用CoreAnimation。
選擇使用動畫樣式需要注意:UIView動畫優先于CoreAnimation動畫
區分不同Anim的方法:1、對于加在一個全局變量上的anima,比如例子里的self.AnimateView ,這是一個全局變量,所以我們在這里可以通過[self.AnimateView.layer animationForKey:]根據動畫不同的key來區分2、然而對于一個非全局的變量,比如demo中的progressLayer,可以用KVO:[pathAnimation setValue:@"strokeEndAnimation" forKey:@"animationName"];注意這個animationName是我們自己設定的。
寫一個動畫比較準確的順序:先改變model layer的屬性,再應用動畫。即先賦值給目標對象的屬性,然后再添加動畫。
UIBezierPath貝塞爾弧線常用方法:
//根據一個矩形畫曲線
+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect
//根據矩形框的內切圓畫曲線
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect
//根據矩形畫帶圓角的曲線
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
//在矩形中,可以針對四角中的某個角加圓角
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
參數:
corners:枚舉值,可以選擇某個角
cornerRadii:圓角的大小
//以某個中心點畫弧線
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
參數:
center:弧線中心點的坐標
radius:弧線所在圓的半徑
startAngle:弧線開始的角度值
endAngle:弧線結束的角度值
clockwise:是否順時針畫弧線
//畫二元曲線,一般和moveToPoint配合使用
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
參數:
endPoint:曲線的終點
controlPoint:畫曲線的基準點
//以三個點畫一段曲線,一般和moveToPoint配合使用
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
參數:
endPoint:曲線的終點
controlPoint1:畫曲線的第一個基準點
controlPoint2:畫曲線的第二個基準點
推薦:網站1