iOS CoreAnimation
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
前言:這篇文章太全了,忍不住就轉(zhuǎn)了,原地址?CoreAnimation,另外前面寫過(guò)一篇簡(jiǎn)單的動(dòng)畫(huà)IOS簡(jiǎn)單動(dòng)畫(huà)
核心動(dòng)畫(huà),開(kāi)發(fā)人員可以為他們的應(yīng)用創(chuàng)建動(dòng)態(tài)用戶界面,而無(wú)需使用低級(jí)別的圖形 API,如 OpenGL 來(lái)獲取高效的動(dòng)畫(huà)性能。?
前言,核心動(dòng)畫(huà)的好處
1.簡(jiǎn)單易用的高性能混合編程模型。
2.類似視圖一樣,你可以通過(guò)使用圖層來(lái)創(chuàng)建復(fù)雜的接口。? ?通過(guò)是CALayer來(lái)使用更復(fù)雜的一些動(dòng)畫(huà)。? ?
3.輕量級(jí)的數(shù)據(jù)結(jié)構(gòu),它可以同時(shí)顯示并讓上百個(gè)圖層產(chǎn)生動(dòng)畫(huà)效果。? ? ?控制多個(gè)CALayer來(lái)顯示動(dòng)畫(huà)效果? ? ???
4.一套簡(jiǎn)單的動(dòng)畫(huà)接口,可以讓你的動(dòng)畫(huà)運(yùn)行在獨(dú)立的線程里面,并可以獨(dú)立于主線程之外。
5.一旦動(dòng)畫(huà)配置完成并啟動(dòng),核心動(dòng)畫(huà)完全控制并獨(dú)立完成相應(yīng)的動(dòng)畫(huà)幀。
6.提高應(yīng)用性能。應(yīng)用程序只當(dāng)發(fā)生改變的時(shí)候才重繪內(nèi)容。再小的應(yīng)用程序也需要改變和提供布局服務(wù)層。核心動(dòng)畫(huà)還消除了在動(dòng)畫(huà)的幀速率上運(yùn)行的應(yīng)用程序代碼。
7.靈活的布局管理模型。包括允許圖層相對(duì)同級(jí)圖層的關(guān)系來(lái)設(shè)置相應(yīng)屬性的位置和大小。? ?可以使用CALayer來(lái)更靈活的進(jìn)行布局。??
1.1 Core animation類
1.提供顯示內(nèi)容的圖層類。CALayer
2.動(dòng)畫(huà)和計(jì)時(shí)類。Animation and Timing Classes
3.布局和約束類。
4.事務(wù)類,在原子更新的時(shí)候組合圖層類。核心動(dòng)畫(huà)的基礎(chǔ)類包含在 Quartz 核心框架(Quartz Core framework)里面,雖然它的其他圖層類在其他框架里面定義。下圖顯示了核心動(dòng)畫(huà)的類層次結(jié)構(gòu)。?
?1.1.1 圖層類? ?
層類(Layer Classes)?
?Layer Classes是core animation的基礎(chǔ)。Layer Classes提供了一個(gè)抽象的概念,這個(gè)概念對(duì)于那些使用NSview和UIview的開(kāi)發(fā)者來(lái)說(shuō)是很熟悉的。基礎(chǔ)層是由CAlayer類提供的,CAlayer是所有Core Animation層的父類。?? ?
同一個(gè)視圖類的實(shí)例一樣,一個(gè)CAlayer實(shí)例也有一個(gè)單獨(dú)的superlayer和上面所有的子層(sublayers),它創(chuàng)建了一個(gè)有層次結(jié)構(gòu)的層,我們稱之為layer tree。layers的繪制就像views一樣是從后向前繪制的,繪制的時(shí)候我們要指定其相對(duì)與他們的superlayer的集合形狀,同時(shí)還需要?jiǎng)?chuàng)建一個(gè)局部的坐標(biāo)系。layers可以做一些更復(fù)雜的操作,例如rotate(旋轉(zhuǎn)),skew(傾斜),scale(放縮),和project the layer content(層的投影)。? ?
圖層的內(nèi)容提供
(1)直接設(shè)置層的content屬性到一個(gè)core graphics圖,或者通過(guò)delegation來(lái)設(shè)置
(2)提供一個(gè)代理直接繪制到Core Graphics image context(核心圖形的上下文)
(3)設(shè)置任意數(shù)量的所有層共有的可視的風(fēng)格屬性。例如:backgroundColor(背景色),opacity(透明度)和masking(遮罩)。max os x應(yīng)用通過(guò)使用core image filters來(lái)達(dá)到這種可視化的屬性。
(4)子類化CAlayer,同時(shí)在更多的封裝方式中完成上面的任意技術(shù)。?
?
? 三個(gè)重要的子類
(1)CAScrollLayer:它是CALayer的一個(gè)子類,用來(lái)顯示layer的某一部分,一個(gè)CAScrollLayer對(duì)象的滾動(dòng)區(qū)域是由其子層的布局來(lái)定義的。CAScrollLayer沒(méi)有提供鍵盤或者鼠標(biāo)事件,也沒(méi)有提供明顯的滾動(dòng)條。
(2)CATextLayer:它是一個(gè)很方便就可以從string和attributed string創(chuàng)建layer的content的類。
(3)CATiledLayer:它允許在增量階段顯示大和復(fù)雜的圖像(就是將圖形進(jìn)行分塊顯示,來(lái)減少性能開(kāi)銷)
?
? ?Mac OS X 額外的類CAOpenGLLayer 提供了一個(gè)OpenGL渲染環(huán)境。你必須繼承這個(gè)類來(lái)使用 OpenGL 提供的內(nèi)容。內(nèi)容可以是靜態(tài)的,或可隨著時(shí)間的推移更新。QCCompositionLayer(由Quartz框架提供)可以把Quartz合成的內(nèi)容動(dòng)畫(huà) 顯示。QTMovieLayer and QTCaptureLayer (QTKit 框架提供)提供播放 QuickTime 影片和視頻直播。
?
? ?iOS 獨(dú)特的CALayerCAEAGLLayer 提供了一個(gè)OpenGLES渲染環(huán)境。CALayer 的類引入鍵-值編碼兼容的容器類概念,也就是說(shuō)一個(gè)類可以使用鍵 - 值編碼的方法存儲(chǔ)任意值,而無(wú)需創(chuàng)建一個(gè)子類。CALayer 的還擴(kuò)展了 NSKeyValueCoding 的非正式協(xié)議,加入默認(rèn)鍵值和額外的結(jié)構(gòu)類型的自動(dòng)對(duì)象包裝 (CGPoint,CGSize,CGRect,CGAffineTransform 和 CATransform3D)的支持,并 提供許多這些結(jié)構(gòu)的關(guān)鍵路徑領(lǐng)域的訪問(wèn)。CALayer也管理動(dòng)畫(huà)和與其相關(guān)的layer的actions。layers接收一些從layer tree中觸發(fā)的insert和remove消息,修改被創(chuàng)建的layer的屬性,或者指明開(kāi)發(fā)者的需求。這些actions通常都會(huì)導(dǎo)致動(dòng)畫(huà)的產(chǎn)生。
?
1.1.2 動(dòng)畫(huà)和計(jì)時(shí)類(Animation and Timing Classes)? ??
?????圖層的很多可視化屬性是可以隱式動(dòng)畫(huà)的。通過(guò)簡(jiǎn)單的改變圖層的可動(dòng)畫(huà)顯示的屬性,可以讓圖層現(xiàn)有屬性從當(dāng)前值動(dòng)畫(huà)漸變到新的屬性值。例如設(shè)置圖層的 hidden 屬性為 YES 將會(huì)觸發(fā)動(dòng)畫(huà)使層逐漸淡出。
? ??默認(rèn)動(dòng)畫(huà)?
? ?大多數(shù)動(dòng)畫(huà)屬性擁有自己關(guān)聯(lián)的默認(rèn)動(dòng)畫(huà), 你可以輕松地定制和替換。我們將會(huì)在后面“動(dòng)畫(huà)屬性”部分列出一個(gè)完整的動(dòng)畫(huà)屬性列表和它們相應(yīng)的默認(rèn)動(dòng)畫(huà)。
? ?關(guān)于哪些屬性執(zhí)行的是什么默認(rèn)動(dòng)畫(huà)效果請(qǐng)參考apple官方文檔?
? ?顯式動(dòng)畫(huà)
? ?動(dòng)畫(huà)的屬性也可以顯式動(dòng)畫(huà)。要顯式動(dòng)畫(huà)的屬性,你需要?jiǎng)?chuàng)建核心動(dòng)畫(huà)動(dòng)畫(huà)類的一個(gè)實(shí)例,并指定所需的視覺(jué)效果。顯式動(dòng)畫(huà)不會(huì)改變?cè)?、屬性的值,它只是用于動(dòng)畫(huà)顯示。?
?
? ? 核心動(dòng)畫(huà)的動(dòng)畫(huà)類使用基本的動(dòng)畫(huà)和關(guān)鍵幀動(dòng)畫(huà)把圖層的內(nèi)容和選取的屬性動(dòng)畫(huà)的顯示出來(lái)。所有核心動(dòng)畫(huà)的動(dòng)畫(huà)類都是從 CAAnimation 類繼承而來(lái)。
CAAnimation 實(shí)現(xiàn)了 CAMediaTiming 協(xié)議,提供了動(dòng)畫(huà)的持續(xù)時(shí)間,速度,和重復(fù)計(jì)數(shù)。 CAAnimation 也實(shí)現(xiàn)了 CAAction 協(xié)議。該協(xié)議為圖層觸發(fā)一個(gè)動(dòng)畫(huà)動(dòng)作提供了提供標(biāo)準(zhǔn)化響應(yīng)。動(dòng)畫(huà)類同時(shí)定義了一個(gè)使用貝塞爾曲線來(lái)描述動(dòng)畫(huà)改變的時(shí)間函數(shù)。例如,一個(gè) 勻速時(shí)間函數(shù)(linear timing function)在動(dòng)畫(huà)的整個(gè)生命周期里面一直保持速度不變, 而漸緩時(shí)間函數(shù)(ease-out timing function)則在動(dòng)畫(huà)接近其生命周期的時(shí)候減慢速度。核心動(dòng)畫(huà)額外提供了一系列抽象的和細(xì)化的動(dòng)畫(huà)類,比如:CATransition 提供了一個(gè)圖層變化的過(guò)渡效果,它能影響圖層的整個(gè)內(nèi)容。 動(dòng)畫(huà)進(jìn)行的時(shí)候淡入淡出(fade)、推(push)、顯露(reveal)圖層的內(nèi)容。這些過(guò)渡效 果可以擴(kuò)展到你自己定制的 Core Image 濾鏡。CAAnimationGroup 允許一系列動(dòng)畫(huà)效果組合在一起,并行顯示動(dòng)畫(huà)。
?
多個(gè)動(dòng)畫(huà)效果疊加,比如在執(zhí)行動(dòng)畫(huà)的過(guò)程中需要同時(shí)修改position,alpha, frame等屬性,可以將三個(gè)動(dòng)畫(huà)合成一起執(zhí)行。
CAAnimationGroup?*animGroup?=?[CAAnimationGroup?animation];? animGroup.animations?=?[NSArray?arrayWithObjects:moveAnim,scaleAnim,opacityAnim,?nil]; animGroup.duration?=?1; [view.layer?addAnimation:animGroup?forKey:nil];CAPropertyAnimation 是一個(gè)抽象的子類,它支持動(dòng)畫(huà)的顯示圖層的關(guān)鍵路 徑中指定的屬性一般不直接使用,而是使用它的子類,CABasicAnimation,CAKeyframeAnimation. 在它的子類里修改屬性來(lái)運(yùn)行動(dòng)畫(huà)。
?
CABasicAnimation 簡(jiǎn)單的為圖層的屬性提供修改。?很多圖層的屬性修改默認(rèn)會(huì)執(zhí)行這個(gè)動(dòng)畫(huà)類。比如大小,透明度,顏色等屬性
CAKeyframeAnimation 支持關(guān)鍵幀動(dòng)畫(huà),你可以指定的圖層屬性的關(guān)鍵路徑動(dòng)畫(huà),包括動(dòng)畫(huà)的每個(gè)階段的價(jià)值,以及關(guān)鍵幀時(shí)間和計(jì)時(shí)功能的一系列值。在 動(dòng)畫(huà)運(yùn)行是,每個(gè)值被特定的插入值替代。核心動(dòng)畫(huà) 和 Cocoa Animation 同時(shí)使用這些動(dòng)畫(huà)類。使用動(dòng)畫(huà)描述,是因?yàn)檫@些類涉及到核心動(dòng)畫(huà),這些將會(huì)在Animation Types and Timing Programming Guide 有較深入的討論。
?
1.1.3 布局管理器類
Application Kit 的視圖類相對(duì)于 superlayer 提供了經(jīng)典的“struts and springs”定位 模型。圖層類兼容這個(gè)模型,同時(shí) Mac OS X 上面的核心動(dòng)畫(huà)提供了一套更加靈活 的布局管理機(jī)制,它允許開(kāi)發(fā)者自己修改布局管理器。核心動(dòng)畫(huà)的 CAConstraint 類 是一個(gè)布局管理器,它可以指定子圖層類限制于你指定的約束集合。每個(gè)約束 (CAConstraint 類的實(shí)例封裝)描述層的幾何屬性(左,右,頂部或底部的邊緣或水 平或垂直中心)的關(guān)系,關(guān)系到其同級(jí)之一的幾何屬性層或 superlayer。通用的布局管理器和約束性布局管理器將會(huì)在“布局核心動(dòng)畫(huà)的圖層”部分討論。
?1.1.4 事務(wù)管理類?? ?
?圖層的動(dòng)畫(huà)屬性的每一個(gè)修改必然是事務(wù)的一個(gè)部分。CATransaction 是核心動(dòng)畫(huà)里面負(fù)責(zé)協(xié)調(diào)多個(gè)動(dòng)畫(huà)原子更新顯示操作。事務(wù)支持嵌套使用。?????
第二章 核心動(dòng)畫(huà)渲染框架?
可能有人會(huì)很好奇CoreAnimation是如何渲染動(dòng)畫(huà),動(dòng)畫(huà)是如何生成的。?在core aniamtion和cocoa view之間有很大的相似之處,他們之間最大的概念上的分歧就是layer不直接渲染到屏幕上。在MVC的設(shè)計(jì)模式下,NSView和UIView是視圖對(duì)象,core animation層實(shí)際上是模型對(duì)象。他們封裝了幾何圖形,時(shí)間和可視屬性,同時(shí)提供顯示的內(nèi)容,但是實(shí)際上顯示并不是layer的責(zé)任。每一個(gè)可視的layer tree后面都有兩個(gè)相應(yīng)的tree:presentation tree和render tree。如下圖所示:
layer tree包含了每個(gè)layer的對(duì)象模型。當(dāng)你為一個(gè)layer的屬性設(shè)置一個(gè)的時(shí)候,他們的值就是你設(shè)置的。The presentation tree包含了當(dāng)前正在呈現(xiàn)給用戶作為動(dòng)畫(huà)發(fā)生的值。例如:對(duì)一個(gè)layer的backgroundcolor設(shè)置一個(gè)新的值的時(shí)候,在layer tree中的值會(huì)馬上改變。然而,在presentation tree的相應(yīng)層的backgroundcolor的值隨著要顯示給用戶的插值顏色會(huì)被更新。當(dāng)渲染一個(gè)layer的時(shí)候,the render-tree會(huì)使用presentation-tree的值。the render-tree的責(zé)任就是執(zhí)行獨(dú)立與程序活動(dòng)的合成操作;渲染是在一個(gè)單獨(dú)進(jìn)程或者線程中,以便使其對(duì)應(yīng)用程序的run loop影響最小。當(dāng)一個(gè)動(dòng)畫(huà)在執(zhí)行的過(guò)程中,你可以查詢相應(yīng)的presentation layer的實(shí)例。如果你打算改變當(dāng)前的動(dòng)畫(huà)并且從當(dāng)前顯示狀態(tài)開(kāi)始一個(gè)新的動(dòng)畫(huà),這是非常有用的。???
第三章 ?圖層的幾何和變化
?
?圖層的幾何變化涉及到修改圖層的幾何屬性,比如大小,錨點(diǎn),圓角等屬性等等,這個(gè)部分詳細(xì)的可以查看Quartz 2D 的文檔,這個(gè)文檔講的比較詳細(xì)。?
?3.1圖層的坐標(biāo)系
圖層的坐標(biāo)系在不同平臺(tái)上面具有差異性。在 iOS 系統(tǒng)中,默認(rèn)的坐標(biāo)系統(tǒng)原點(diǎn) 在圖層的中心左上角地方,原點(diǎn)向右和向下為正值。在 Mac OS X 系統(tǒng)中,默認(rèn)的坐 標(biāo)系原點(diǎn)在圖層的中心左下角地方,原點(diǎn)向右和向上為正值。坐標(biāo)系的所有值都是浮 點(diǎn)類型。你在任何平臺(tái)上面創(chuàng)建的圖層都采用該平臺(tái)默認(rèn)的坐標(biāo)系。
每個(gè)圖層定義并維護(hù)自己的坐標(biāo)系,它里面的全部?jī)?nèi)容都由此相關(guān)的坐標(biāo)系指定 位置。該準(zhǔn)則同時(shí)適應(yīng)于圖層自己的內(nèi)容和它的任何子圖層。因?yàn)槿魏螆D層定義了它 自己的坐標(biāo)系,CALayer 類提供相應(yīng)的方法用于從一個(gè)圖層坐標(biāo)系的點(diǎn)、矩形、大小 值轉(zhuǎn)化為另一個(gè)圖層坐標(biāo)系相應(yīng)的值。一些基于圖層的屬性使用單元坐標(biāo)空間測(cè)量它們的值。單元坐標(biāo)空間指定圖層邊 界的相對(duì)值,而不是絕對(duì)值。單元坐標(biāo)空間給定的 x 和 y 的值總是在 0.0 到 1.0 之間。 指定一個(gè)沿 X 軸的值為 0.0 的點(diǎn),得到的是圖層左邊緣的一個(gè)點(diǎn),而指定一個(gè) 1.0 的點(diǎn),則是圖層右邊緣的一個(gè)點(diǎn)。(對(duì) Y 軸而言,如果是在 iOS 系統(tǒng),則 0.0 對(duì)應(yīng)于 頂部的點(diǎn),而 1.0 則是底部的點(diǎn),而在 Mac OS X 系統(tǒng),得到的剛好相反,就如之前 提到的坐標(biāo)系不同一樣)。而點(diǎn)(0.5,0.5)則剛好是圖層的中心點(diǎn)。
?
?3.2指定圖層的幾何
雖然圖層和圖層樹(shù)與視圖和視圖的結(jié)構(gòu)在很多方面具有相似性,但是圖層的幾何 卻不同,它更加簡(jiǎn)單通俗。圖層的所有幾何屬性,包括圖層的矩陣變換,都可以隱式 和顯式動(dòng)畫(huà)。
? 下圖顯示可以在上下文中指定圖層幾何的屬性:?
圖層的 position 屬性是一個(gè) CGPoint 的值,它指定圖層相當(dāng)于它父圖層的位置, 該值基于父圖層的坐標(biāo)系。圖層的 bounds 屬性是一個(gè) CGRect 的值,指定圖層的大小(bounds.size)和圖層的 原點(diǎn)(bounds.origin)。當(dāng)你重寫圖層的重畫(huà)方法的時(shí)候,bounds 的原點(diǎn)可以作為圖形 上下文的原點(diǎn)。圖層擁有一個(gè)隱式的 frame,它是 position,bounds,anchorPoint 和 transform 屬性 的一部分。設(shè)置新的 frame 將會(huì)相應(yīng)的改變圖層的 position 和 bounds 屬性,但是 frame 本身并沒(méi)有被保存。但是設(shè)置新的 frame 時(shí)候,bounds 的原點(diǎn)不受干擾,bounds 的大 小變?yōu)?frame 的大小,即 bounds.size=frame.size。圖層的位置被設(shè)置為相對(duì)于錨點(diǎn) (anchor point)的適合位置。當(dāng)你設(shè)置 frame 的值的時(shí)候,它的計(jì)算方式和 position、 bounds、和 anchorPoint 的屬性相關(guān)。圖層的 anchorPoint 屬性是一個(gè) CGPoint 值,它指定了一個(gè)基于圖層 bounds 的符 合位置坐標(biāo)系的位置。錨點(diǎn)(anchor point)指定了 bounds 相對(duì)于 position 的值,同 時(shí)也作為變換時(shí)候的支點(diǎn)。錨點(diǎn)使用單元空間坐標(biāo)系表示,(0.0,0.0)點(diǎn)接近圖層 的原點(diǎn),而(1.0,1.0)是原點(diǎn)的對(duì)角點(diǎn)。改變圖層的父圖層的變換屬性(如果存在 的話)將會(huì)影響到 anchorPoint 的方向,具體變化取決于父圖層坐標(biāo)系的 Y 軸。?當(dāng)你設(shè)置圖層的 frame 屬性的時(shí)候,position 會(huì)根據(jù)錨點(diǎn)(anchorPoint)相應(yīng)的改 變,而當(dāng)你設(shè)置圖層的 position 屬性的時(shí)候,bounds 會(huì)根據(jù)錨點(diǎn)(anchorPoint)做相應(yīng)的改變。?
?
下圖描述了基于錨點(diǎn)的三個(gè)示例值:
anchorPoint 默認(rèn)值是(0.5,0.5),位于圖層邊界的中心點(diǎn)(如上圖顯示),B 點(diǎn) 把 anchorPoint 設(shè)置為(0.0,0.5)。最后 C 點(diǎn)(1.0,0.0)把圖層的 position 設(shè)置為 圖層 frame 的右下角。該圖適用于 Mac OS X 的圖層。在 iOS 系統(tǒng)里面,圖層使用不 同的坐標(biāo)系,相應(yīng)的(0.0,0.0)位于左上角,而(1.0,1.0)位于右下角。
圖層的 frame、bounds、position 和 anchorPoint 關(guān)系如下圖所示:?
在該示例中,anchorPoint 默認(rèn)值為(0.5,0.5),位于圖層的中心點(diǎn)。圖層的 position 值為(100.0,100.0),bounds 為(0.0,0.0,120,80.0)。通過(guò)計(jì)算得到圖層的 frame為(40.0,60.0,120.0,80.0)。
如果你新創(chuàng)建一個(gè)圖層,則只有設(shè)置圖層的 frame 為(40.0,60.0,120.0,80.0),相應(yīng)的 position 屬性值將會(huì)自動(dòng)設(shè)置為(100.0,100.0),而 bounds 會(huì)自動(dòng)設(shè)置為 (0.0,0.0,120.0,80.0)。下圖顯示一個(gè)圖層具有相同的 frame(如上圖),但是在該圖中它的 anchorPoint 屬性值被設(shè)置為(0.0,0.0),位于圖層的左下角位置。
?
圖層的 frame 值同樣為(40.0,60.0,120.0,80.0),bounds 的值不變,但是圖層的 position 值已經(jīng)改變?yōu)?40.0,60.0)。
圖層的幾何外形和 Cocoa 視圖另外一個(gè)不同地方是,你可以設(shè)置圖層的一個(gè)邊角 的半徑來(lái)把圖層顯示為圓角。圖層的 cornerRadius 屬性指定了重繪圖層內(nèi)容,剪切子 圖層,繪制圖層的邊界和陰影的時(shí)候時(shí)候圓角的半徑。
圖層的 zPosition 屬性值指定了該圖層位于 Z 軸上面位置,zPosition 用于設(shè)置圖層 相對(duì)于圖層的同級(jí)圖層的可視位置
3.3 圖層的幾何變換
圖層一旦創(chuàng)建,你就可以通過(guò)矩陣變換來(lái)改變一個(gè)圖層的幾何形狀。?CATransform3D 的數(shù)據(jù)結(jié)構(gòu)定義一個(gè)同質(zhì)的三維變換(4x4 CGFloat 值的矩陣),用于 圖層的旋轉(zhuǎn),縮放,偏移,歪斜和應(yīng)用的透視。圖層的兩個(gè)屬性指定了變換矩陣:transform 和 sublayerTransform 屬性。圖層的 transform 屬性指定的矩陣結(jié)合圖層的 anchorPoint 屬性作用于圖層和圖層的子圖層上 面。圖 3 顯示在使用 anchorPoint 默認(rèn)值(0.5,0.5)的時(shí)候旋轉(zhuǎn)和縮放變換如何影響一個(gè)圖層。而圖 4 顯示了同樣的矩陣變換在 anchorPoint 為(0.0,0.0)的時(shí)候如何改變一 個(gè)圖層。圖層的 sublayerTransform 屬性指定的矩陣只會(huì)影響圖層的子圖層,而不會(huì)對(duì) 圖層本身產(chǎn)生影響。你可以通過(guò)以下的任何一個(gè)方法改變 CATransform3D 的數(shù)據(jù)結(jié)構(gòu):(1) 使用CATransform3D函數(shù)(2) 直接修改數(shù)據(jù)結(jié)構(gòu)的成員(3) 使用鍵-值編碼改變鍵路徑
CATransform3DIdentity 是單位矩陣,該矩陣沒(méi)有縮放、旋轉(zhuǎn)、歪斜、透視。把該 矩陣應(yīng)用到圖層上面,會(huì)把圖層幾何屬性修改為默認(rèn)值。?
?3.3.1 變換函數(shù)
使用變換函數(shù)可以在核心動(dòng)畫(huà)里面在操作矩陣。你可以使用這些函數(shù)(如下表)去 創(chuàng)建一個(gè)矩陣一般后面用于改變圖層或者它的子圖層的 transform 和 sublayerTransform屬性。變換函數(shù)或者直接操或者返回一個(gè)CATransform3D的數(shù)據(jù)結(jié) 構(gòu)。這可以讓你能夠構(gòu)建簡(jiǎn)單或復(fù)雜的轉(zhuǎn)換,以便重復(fù)使用。
核心動(dòng)畫(huà) 提供了用于轉(zhuǎn)換矩陣的變換函數(shù) CATransform3DInvert。一般是用反轉(zhuǎn) 點(diǎn)內(nèi)轉(zhuǎn)化對(duì)象提供反向轉(zhuǎn)換。當(dāng)你需要恢復(fù)一個(gè)已經(jīng)被變換了的矩陣的時(shí)候,反轉(zhuǎn)將 會(huì)非常有幫助。反轉(zhuǎn)矩陣乘以逆矩陣值,結(jié)果是原始值。變換函數(shù)同時(shí)允許你把 CATransform3D 矩陣轉(zhuǎn)化為 CGAffineTransform(仿射) 矩陣,前提是 CATransform3D 矩陣采用如下表示方法。
變換函數(shù)同時(shí)提供了可以比較一個(gè)變換矩陣是否是單位矩陣,或者兩個(gè)矩陣是否 相等。
3.3.2 修改變換的數(shù)據(jù)結(jié)構(gòu)
你可以修改 CATransform3D 的數(shù)據(jù)結(jié)構(gòu)的元素為任何其他你想要的數(shù)據(jù)值。清單 1 包含了 CATransform3D 數(shù)據(jù)結(jié)構(gòu)的定義,結(jié)構(gòu)的成員都在其相應(yīng)的矩陣位置。struct CATransform3D? ? ? ? ? ? ? ?{? ? ? ? ? ? ? ? ?CGFloat m11, m12, m13, m14;? ? ? ? ? ? ? ? ?CGFloat m21, m22, m23, m24;? ? ? ? ? ? ? ? ?CGFloat m31, m32, m33, m34;? ? ? ? ? ? ? ? ?CGFloat m41, m42, m43, m44;? ? ? ? ? ? ? ? ?};? ? ? ? ? ? ? ?typedef struct CATransform3D CATransform3D;? ? ? ? ? ? ? ?? ? ? ? ? ? ? ?清單 2 中的示例說(shuō)明了如何配置一個(gè) CATransform3D 一個(gè)角度變換。 ? ? ? ? ? ? ?
3.3.3 通過(guò)鍵值路徑修改變換? ?
核心動(dòng)畫(huà)擴(kuò)展了鍵-值編碼協(xié)議,允許通過(guò)關(guān)鍵路徑獲取和設(shè)置一個(gè)圖層的 CATransform3D 矩陣的值。表 4 描述了圖層的 transform 和 sublayerTransform 屬性的相應(yīng)關(guān)鍵路徑。??
?你不可以通過(guò) Objective-C 2.0 的屬性來(lái)設(shè)置結(jié)構(gòu)域的值,比如下面的代碼將會(huì)無(wú)法正常運(yùn)行:? ?? ?myLayer.transform.rotation.x=0;? ???? ?替換的辦法是,你必須通過(guò) setValue:forKeyPath:或者 valueForKeyPath:方法, 具體如下:? ?? ? ? [myLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"transform.rotation.x"];
?
?3.4 圖層的操作
圖層有一個(gè)圖層樹(shù),既然是樹(shù),就允許添加,插入,刪除,替換相應(yīng)的圖層,
?這些操作都可以通過(guò)已有的api實(shí)現(xiàn),api如下
3.5 圖層的內(nèi)容?
圖層的內(nèi)容提供,是指通過(guò)一種方法來(lái)制定CALayer 實(shí)例的內(nèi)容:?其中有一下三種方式來(lái)提供CAlayer的內(nèi)容? (1)使用包含圖片內(nèi)容的 CGImageRef 來(lái)顯式的設(shè)置圖層的 contents 的屬性。 ? (2)指定一個(gè)委托,它提供或者重繪內(nèi)容。? (3)繼承 CALayer 類重載顯示的函數(shù)。
?
第四章 動(dòng)畫(huà)動(dòng)畫(huà)是當(dāng)今用戶界面的關(guān)鍵因素。當(dāng)使用核心動(dòng)畫(huà)的時(shí)候,動(dòng)畫(huà)是自動(dòng)完成的。 沒(méi)有動(dòng)畫(huà)的循環(huán)和計(jì)數(shù)器。你的應(yīng)用程序不負(fù)負(fù)責(zé)重繪,也不負(fù)責(zé)跟蹤動(dòng)畫(huà)的當(dāng)前狀 態(tài)。動(dòng)畫(huà)在獨(dú)立線程里面自動(dòng)執(zhí)行,沒(méi)有和你的應(yīng)用程序交互。核心動(dòng)畫(huà)提供了一套你可以在你應(yīng)用程序里面使用的動(dòng)畫(huà)類的表現(xiàn):? (1)CABasicAnimation提供了在圖層的屬性值間簡(jiǎn)單的插入。? (2)CAKeyframeAnimation 提供支持關(guān)鍵幀動(dòng)畫(huà)。你指定動(dòng)畫(huà)的一個(gè)圖層屬性的關(guān)鍵路徑,一個(gè)表示在動(dòng)畫(huà)的每個(gè)階段的價(jià)值的數(shù)組,還有一個(gè)關(guān)鍵幀時(shí)間的數(shù)組和時(shí)間函數(shù)。? (3)CATransition提供了一個(gè)影響整個(gè)圖層的內(nèi)容過(guò)渡效果。在動(dòng)畫(huà)顯示過(guò)程中采用淡出(fade)、推出(push)、顯露(reveal)圖層的內(nèi)容。 常用的過(guò)渡效果可以通過(guò)提供你自己定制的核心圖像濾鏡來(lái)擴(kuò)展。除了要指定顯示的動(dòng)畫(huà)類型,你還必須指定動(dòng)畫(huà)的間隔、它的速度(它的插值如何分布在整個(gè)動(dòng)畫(huà)過(guò)程)、動(dòng)畫(huà)循環(huán)時(shí)候的循環(huán)次數(shù)、動(dòng)畫(huà)周期完成的時(shí)候是否自動(dòng) 的反轉(zhuǎn)、還有動(dòng)畫(huà)結(jié)束的時(shí)候它的可視化狀態(tài)。動(dòng)畫(huà)類和 CAMediaTiming 協(xié)議提供 所有這些功能甚至更多的功能。CAAnimation、它的子類、時(shí)序協(xié)議被核心動(dòng)畫(huà)和Cocoa Animation Proxy功能共享。這些類將會(huì)在“動(dòng)畫(huà)類型和時(shí)序編程指南(Animation Types and Timing Programming Guide)”里面詳細(xì)介紹。
? ? ? ? ? ? ?Core Animation 類的繼承關(guān)系圖?
?
下面將針對(duì)上面的知識(shí)做一個(gè)圖片動(dòng)畫(huà)的demo
功能1 :移動(dòng)圖片到右下角
//向右下角縮小移動(dòng)-?(IBAction)buttonClick:(id)sender {CGPoint?fromPoint?=?imageView.center;????//路徑曲線????UIBezierPath?*movePath?=?[UIBezierPath?bezierPath];[movePath?moveToPoint:fromPoint];CGPoint?toPoint?=?CGPointMake(300,?460);[movePath?addQuadCurveToPoint:toPointcontrolPoint:CGPointMake(toPoint.x,fromPoint.y)];????//關(guān)鍵幀????CAKeyframeAnimation?*moveAnim?=?[CAKeyframeAnimation?animationWithKeyPath:@"position"];moveAnim.path?=?movePath.CGPath;moveAnim.removedOnCompletion?=?YES;????//旋轉(zhuǎn)變化????CABasicAnimation?*scaleAnim?=?[CABasicAnimation?animationWithKeyPath:@"transform"];scaleAnim.fromValue?=?[NSValue?valueWithCATransform3D:CATransform3DIdentity];????//x,y軸縮小到0.1,Z?軸不變????scaleAnim.toValue?=?[NSValue?valueWithCATransform3D:CATransform3DMakeScale(0.1,?0.1,?1.0)];scaleAnim.removedOnCompletion?=?YES;????//透明度變化????CABasicAnimation?*opacityAnim?=?[CABasicAnimation?animationWithKeyPath:@"alpha"];opacityAnim.fromValue?=?[NSNumber?numberWithFloat:1.0];opacityAnim.toValue?=?[NSNumber?numberWithFloat:0.1];opacityAnim.removedOnCompletion?=?YES;????//關(guān)鍵幀,旋轉(zhuǎn),透明度組合起來(lái)執(zhí)行????CAAnimationGroup?*animGroup?=?[CAAnimationGroup?animation];animGroup.animations?=?[NSArray?arrayWithObjects:moveAnim,?scaleAnim,opacityAnim,?nil];animGroup.duration?=?1;[imageView.layer?addAnimation:animGroup?forKey:nil]; }?功能2 :向右邊旋轉(zhuǎn)
?//向右邊旋轉(zhuǎn)-?(IBAction)rightRotateBtnClick:(id)sender {CGPoint?fromPoint?=?imageView.center;UIBezierPath?*movePath?=?[UIBezierPath?bezierPath];[movePath?moveToPoint:fromPoint];CGPoint?toPoint?=?CGPointMake(fromPoint.x?+100?,?fromPoint.y)?;[movePath?addLineToPoint:toPoint];CAKeyframeAnimation?*moveAnim?=?[CAKeyframeAnimation?animationWithKeyPath:@"position"];moveAnim.path?=?movePath.CGPath;CABasicAnimation?*scaleAnim?=?[CABasicAnimation?animationWithKeyPath:@"transform"];scaleAnim.fromValue?=?[NSValue?valueWithCATransform3D:CATransform3DIdentity];????//沿Z軸旋轉(zhuǎn)????scaleAnim.toValue?=?[NSValue?valueWithCATransform3D:?CATransform3DMakeRotation(M_PI,0,0,1)];????//沿Y軸旋轉(zhuǎn)???//?scaleAnim.toValue?=?[NSValue?valueWithCATransform3D:?CATransform3DMakeRotation(M_PI,0,1.0,0)];????//沿X軸旋轉(zhuǎn)??//?scaleAnim.toValue?=?[NSValue?valueWithCATransform3D:?CATransform3DMakeRotation(M_PI,1.0,0,0)];????scaleAnim.cumulative?=?YES;scaleAnim.duration?=1;??//旋轉(zhuǎn)2遍,360度????????scaleAnim.repeatCount?=2;imageView.center?=?toPoint;scaleAnim.removedOnCompletion?=?YES;CAAnimationGroup?*animGroup?=?[CAAnimationGroup?animation];animGroup.animations?=?[NSArray?arrayWithObjects:moveAnim,?scaleAnim,?nil];animGroup.duration?=?2;[imageView.layer?addAnimation:animGroup?forKey:nil];}功能3?:圖片旋轉(zhuǎn)360度
//圖片旋轉(zhuǎn)360度-?(IBAction)rota360BtnClick:(id)sender {CABasicAnimation?*animation?=?[?CABasicAnimationanimationWithKeyPath:?@"transform"?];animation.fromValue?=?[NSValue?valueWithCATransform3D:CATransform3DIdentity];????//圍繞Z軸旋轉(zhuǎn),垂直與屏幕????animation.toValue?=?[?NSValue?valueWithCATransform3D:?CATransform3DMakeRotation(M_PI,?0,?0,?1.0)?];animation.duration?=?1;????//旋轉(zhuǎn)效果累計(jì),先轉(zhuǎn)180度,接著再旋轉(zhuǎn)180度,從而實(shí)現(xiàn)360旋轉(zhuǎn)???animation.cumulative?=?YES;animation.repeatCount?=?2;????//在圖片邊緣添加一個(gè)像素的透明區(qū)域,去圖片鋸齒????CGRect?imageRrect?=?CGRectMake(0,?0,imageView.frame.size.width,?imageView.frame.size.height);UIGraphicsBeginImageContext(imageRrect.size);?[imageView.image?drawInRect:CGRectMake(1,1,imageView.frame.size.width-2,imageView.frame.size.height-2)];imageView.image?=?UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();[imageView.layer?addAnimation:animation?forKey:nil]; }
---------------------------------------------------------------------------------------華麗的分割線---------------------------------------------------------------------------------------
CABasicAnimation 基本動(dòng)畫(huà)
+(CABasicAnimation?*)opacityForever_Animation:(float)time?//永久閃爍的動(dòng)畫(huà)
{
? ??CABasicAnimation?*animation=[CABasicAnimation?animationWithKeyPath:@"opacity"];
? ? animation.fromValue=[NSNumber?numberWithFloat:1.0];
? ? animation.toValue=[NSNumber?numberWithFloat:0.0];
? ? animation.autoreverses=YES;
? ? animation.duration=time;
? ? animation.repeatCount=FLT_MAX;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ??return?animation;
}
?
+(CABasicAnimation?*)opacityTimes_Animation:(float)repeatTimes durTimes:(float)time;?//有閃爍次數(shù)的動(dòng)畫(huà)
{
? ??CABasicAnimation?*animation=[CABasicAnimation?animationWithKeyPath:@"opacity"];
? ? animation.fromValue=[NSNumber?numberWithFloat:1.0];
? ? animation.toValue=[NSNumber?numberWithFloat:0.4];
? ? animation.repeatCount=repeatTimes;
? ? animation.duration=time;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ? animation.timingFunction=[CAMediaTimingFunction?functionWithName:kCAMediaTimingFunctionEaseIn];
? ? animation.autoreverses=YES;
? ??return? animation;
}
?
+(CABasicAnimation?*)moveX:(float)time X:(NSNumber?*)x?//橫向移動(dòng)
{
? ??CABasicAnimation?*animation=[CABasicAnimation?animationWithKeyPath:@"transform.translation.x"];
? ? animation.toValue=x;
? ? animation.duration=time;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ??return?animation;
}
?
+(CABasicAnimation?*)moveY:(float)time Y:(NSNumber?*)y?//縱向移動(dòng)
{
? ??CABasicAnimation?*animation=[CABasicAnimation?animationWithKeyPath:@"transform.translation.y"];
? ? animation.toValue=y;
? ? animation.duration=time;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ??return?animation;
}
?
+(CABasicAnimation?*)scale:(NSNumber?*)Multiple orgin:(NSNumber?*)orginMultiple durTimes:(float)time Rep:(float)repeatTimes?//縮放
{
? ??CABasicAnimation?*animation=[CABasicAnimation?animationWithKeyPath:@"transform.scale"];
? ? animation.fromValue=orginMultiple;
? ? animation.toValue=Multiple;
? ? animation.duration=time;
? ? animation.autoreverses=YES;
? ? animation.repeatCount=repeatTimes;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ??return?animation;
}
?
+(CAAnimationGroup?*)groupAnimation:(NSArray?*)animationAry durTimes:(float)time Rep:(float)repeatTimes?//組合動(dòng)畫(huà)
{
? ??CAAnimationGroup?*animation=[CAAnimationGroup?animation];
? ? animation.animations=animationAry;
? ? animation.duration=time;
? ? animation.repeatCount=repeatTimes;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ??return?animation;
}
?
+(CAKeyframeAnimation?*)keyframeAniamtion:(CGMutablePathRef)path durTimes:(float)time Rep:(float)repeatTimes//路徑動(dòng)畫(huà)
{
? ??CAKeyframeAnimation?*animation=[CAKeyframeAnimation?animationWithKeyPath:@"position"];
? ? animation.path=path;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ? animation.timingFunction=[CAMediaTimingFunction?functionWithName:kCAMediaTimingFunctionEaseIn];
? ? animation.autoreverses=NO;
? ? animation.duration=time;
? ? animation.repeatCount=repeatTimes;
? ??return?animation;
}
?
+(CABasicAnimation?*)movepoint:(CGPoint?)point?//點(diǎn)移動(dòng)
{
? ??CABasicAnimation?*animation=[CABasicAnimation?animationWithKeyPath:@"transform.translation"];
? ? animation.toValue=[NSValue?valueWithCGPoint:point];
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ??return?animation;
}
?
+(CABasicAnimation?*)rotation:(float)dur degree:(float)degree direction:(int)direction repeatCount:(int)repeatCount?//旋轉(zhuǎn)
{
? ??CATransform3D?rotationTransform? =?CATransform3DMakeRotation(degree,?0,?0,direction);
? ??CABasicAnimation* animation;
? ? animation = [CABasicAnimation?animationWithKeyPath:@"transform"];
?
animation.toValue= [NSValue?valueWithCATransform3D:rotationTransform];
? ? animation.duration= dur;
animation.autoreverses=?NO;
? ? animation.cumulative=?YES;
? ? animation.removedOnCompletion=NO;
? ? animation.fillMode=kCAFillModeForwards;
? ? animation.repeatCount= repeatCount;?
animation.delegate=?self;
?
return?animation;
}
轉(zhuǎn)載于:https://my.oschina.net/wolx/blog/389778
總結(jié)
以上是生活随笔為你收集整理的iOS CoreAnimation的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 免费商用字体有哪些
- 下一篇: 数据挖掘开源项目立项