實現(xiàn)動畫方式深度解析(七) —— Core Animation之Setting Up Layer Objects(四)

版本記錄

版本號 時間
V1.0 2017.09.21

前言

app中好的炫的動畫可以讓用戶耳目一新厦取,為產(chǎn)品增色不少革半,關(guān)于動畫的實現(xiàn)我們可以用基本動畫丛晦、關(guān)鍵幀動畫尔苦、序列幀動畫以及基于CoreGraphic的動畫等等涩馆,接下來這幾篇我就介紹下我可以想到的幾種動畫繪制方法。具體Demo示例已開源到Github —— 刀客傳奇允坚,感興趣的可以看我寫的另外幾篇魂那。
1. 實現(xiàn)動畫方式深度解析(一) —— 播放GIF動畫(一)
2. 實現(xiàn)動畫方式深度解析(二) —— 播放GIF動畫之框架FLAnimatedImage的使用(二)
3. 實現(xiàn)動畫方式深度解析(三) —— 播放序列幀動畫(一)
4. 實現(xiàn)動畫方式深度解析(四) —— QuartzCore框架(一)
5. 實現(xiàn)動畫方式深度解析(五) —— QuartzCore框架之CoreAnimation(二)
6. 實現(xiàn)動畫方式深度解析(六) —— Core Animation Basics(三)

Setting Up Layer Objects - 設(shè)置層layer對象

圖層對象是您使用Core Animation進行的所有操作的核心。 圖層管理您的app的可視內(nèi)容稠项,并提供修改該內(nèi)容的樣式和視覺外觀的選項涯雅。 盡管iOS app已自動啟用圖層支持,但OS X app的開發(fā)人員必須明確地啟用它展运,才能充分利用性能優(yōu)勢斩芭。 啟用后,您需要了解如何配置和操作app的圖層以獲取所需的效果乐疆。


Enabling Core Animation Support in Your App - 開啟你的App CoreAnimation支持

在iOS應(yīng)用程序中划乖,始終啟用核心動畫Core Animation,每個視圖都由圖層layer支持挤土。 在OS X中琴庵,應(yīng)用程序必須通過執(zhí)行以下操作來顯式啟用Core Animation支持:

  • 鏈接到QuartzCore框架。 (只有在明確使用Core Animation界面的情況下,iOS app才能與此框架鏈接迷殿。)
  • 通過執(zhí)行以下操作之一為一個或多個 NSView對象啟用圖層支持:
    • 在您的nib文件中儿礼,使用View Effects inspector檢查器為您的視圖啟用圖層支持。 檢查器將顯示所選視圖及其子視圖的復選框庆寺。 建議您盡可能在窗口的內(nèi)容視圖中啟用圖層支持蚊夫。
    • 對于以編程方式創(chuàng)建的視圖,請調(diào)用視圖的setWantsLayer:方法懦尝,并傳遞值為YES以指示視圖應(yīng)使用圖層layer知纷。

以上述方式之一啟用的層支持創(chuàng)建了層支持的視圖。 通過層layer支持的視圖陵霉,系統(tǒng)負責創(chuàng)建底層圖層對象并保持該層更新琅轧。 在OS X中,也可以創(chuàng)建一個層托管視圖踊挠,由此您的app實際創(chuàng)建和管理底層圖層對象乍桂。 (您不能在iOS中創(chuàng)建層托管視圖。)有關(guān)如何創(chuàng)建層托管視圖的詳細信息效床,請參閱Layer Hosting Lets You Change the Layer Object in OS X睹酌。


Changing the Layer Object Associated with a View - 改變與視圖對象關(guān)聯(lián)的層對象

默認情況下,層支持的視圖創(chuàng)建CALayer類的實例剩檀,并且在大多數(shù)情況下憋沿,可能不需要不同類型的圖層對象。 然而谨朝,Core Animation提供了不同的層類卤妒,每個層都提供了您可能會發(fā)現(xiàn)有用的專門功能甥绿。 選擇不同的層類可以使您以簡單的方式提高性能或支持特定類型的內(nèi)容字币。 例如,CATiledLayer類被優(yōu)化以有效的方式顯示大圖像共缕。

1. Changing the Layer Class Used by UIView - 使用UIView改變layer類

您可以通過重寫視圖的 layerClass方法并返回不同的類對象來更改iOS視圖使用的圖層類型洗出。 大多數(shù)iOS視圖創(chuàng)建一個CALayer對象,并將該層用作其內(nèi)容的后備存儲图谷。 對于大多數(shù)你的視圖翩活,這個默認選擇是一個很好的選擇,您不需要更改它便贵。 但是菠镇,在某些情況下,您可能會發(fā)現(xiàn)不同的層類更合適承璃。 例如利耍,您可能希望在以下情況下更改圖層類:

  • 你的視圖使用Metal或者OpenGL ES進行繪制,在這種情況下,你可以使用CAMetalLayerCAEAGLLayer隘梨。
  • 有一個專門的層類提供更好的性能程癌。
  • 您想要利用一些專門的核心動畫層類,如粒子發(fā)射器或復制器轴猎。

更改視圖的層類非常簡單嵌莉,下面代碼中顯示了一個示例。 所有你需要做的是重寫layerClass方法并返回要使用的類對象捻脖。 在顯示之前锐峭,視圖調(diào)用layerClass方法,并使用返回的類為其自身創(chuàng)建一個新的圖層對象郎仆。 創(chuàng)建后只祠,視圖的圖層對象無法更改。

+ (Class) layerClass {
   return [CAMetalLayer class];
}

對于layer類有哪些和怎么使用它們扰肌,可以參考 Different Layer Classes Provide Specialized Behaviors抛寝。

2. Changing the Layer Class Used By NSView - 使用NSView改變layer類

您可以通過重寫makeBackingLayer方法來更改NSView對象使用的默認層類。 在實現(xiàn)此方法時曙旭,創(chuàng)建并返回您希望AppKit使用的圖層對象來支持自定義視圖盗舰。 您可以在要使用自定義圖層(如滾動或平鋪圖層)的情況下重寫此方法。

對于layer類有哪些和怎么使用它們桂躏,可以參考 Different Layer Classes Provide Specialized Behaviors钻趋。

3. Layer Hosting Lets You Change the Layer Object in OS X - 層委托允許您更改OS X中的圖層對象

層托管視圖是一個NSView對象,您可以為其自己創(chuàng)建和管理底層圖層對象剂习。 在您想要控制與視圖關(guān)聯(lián)的圖層對象類型的情況下蛮位,可以使用圖層托管。 例如鳞绕,您可以創(chuàng)建一個圖層托管視圖失仁,以便您可以分配除默認CALayer類之外的圖層類。 您也可以在要使用單個視圖來管理獨立圖層的層次結(jié)構(gòu)的情況下使用它们何。

當您調(diào)用視圖的setLayer:方法并提供一個圖層對象時萄焦,AppKit會對該圖層進行切換。 通常冤竹,AppKit更新視圖的圖層對象拂封,但是在圖層托管情況下,它不適用于大多數(shù)屬性鹦蠕。

要創(chuàng)建層托管視圖冒签,請在顯示屏幕視圖之前創(chuàng)建圖層對象并將其與視圖相關(guān)聯(lián),如下面代碼所示钟病。 除了設(shè)置層對象之外萧恕,還必須調(diào)用setWantsLayer:方法來讓視圖知道應(yīng)該使用圖層霜定。

// Creating a layer-hosting view
// Create myView...
 
[myView setWantsLayer:YES];
CATiledLayer* hostedLayer = [CATiledLayer layer];
[myView setLayer:hostedLayer];
 
// Add myView to a view hierarchy

如果您自己選擇托管圖層,則必須自己設(shè)置contentsScale屬性廊鸥,并在適當?shù)臅r候提供高分辨率的內(nèi)容望浩。 有關(guān)高分辨率內(nèi)容和比例因子的更多信息,請參閱Working with High-Resolution Images惰说。

4. Different Layer Classes Provide Specialized Behaviors - 不同的層類提供專門的行為

核心動畫定義了許多標準層類磨德,每個類都是針對特定用例設(shè)計的。 CALayer類是所有圖層對象的根類吆视。 它定義了所有層對象必須支持的行為典挑,并且是由層支持的視圖使用的默認類型。 但是啦吧,您也可以指定下表中的一個層類您觉。

下表列出來就是CALayer及其子類。

使用
CAEmitterLayer 用于實現(xiàn)基于核心動畫的粒子發(fā)射器系統(tǒng)授滓。 發(fā)射體層對象控制粒子的產(chǎn)生及其起源琳水。
CAGradientLayer 用于繪制填充圖層形狀的顏色漸變(在任何圓角的邊界內(nèi))。
CAMetalLayer 用于設(shè)置和銷售可繪制的紋理般堆,使用Metal渲染圖層內(nèi)容在孝。
CAEAGLLayer/CAOpenGLLayer 用于設(shè)置存儲和上下文,以便使用OpenGL ES(iOS)和OpenGL(OS X)進行圖層內(nèi)容渲染淮摔。
CAReplicatorLayer 當您想要自動制作一個或多個子圖層的副本時使用私沮。 復制器為您提供副本,并使用您指定的屬性來更改副本的外觀或?qū)傩?/td>
CAScrollLayer 用于管理由多個子層組成的大型可滾動區(qū)域和橙。
CAShapeLayer 用于繪制立方貝塞爾樣條仔燕。 形狀層對于繪制基于路徑的形狀是有利的,因為它們總是導致清晰的路徑魔招,而不是您繪制到圖層的后備存儲中的路徑晰搀,而在縮放時它不會看起來好。 然而仆百,清晰的結(jié)果確實涉及渲染主線程上的形狀并緩存結(jié)果厕隧。
CATextLayer 用于渲染純文本或者富文本奔脐。
CATiledLayer 用于管理可分為較小的圖塊和單獨渲染的大圖像俄周,并支持放大和縮小內(nèi)容。
CATransformLayer 用于渲染真正的3D層次結(jié)構(gòu)髓迎,而不是由其他層類實現(xiàn)的平坦層層次結(jié)構(gòu)
QCCompositionLayer 用于渲染Quartz Composer構(gòu)圖峦朗。 (僅適用于OS X)

Providing a Layer’s Contents - 提供圖層內(nèi)容

圖層是管理由您的應(yīng)用程序提供的內(nèi)容的數(shù)據(jù)對象。 圖層的內(nèi)容由包含要顯示的可視數(shù)據(jù)的位圖組成排龄。 您可以通過以下三種方式之一提供該位圖的內(nèi)容:

  • 將圖像對象直接分配給圖層對象的內(nèi)容屬性波势。 (這種技術(shù)最適用于從不或很少改變的圖層內(nèi)容。)
  • 將一個代理對象賦值給圖層,讓代理繪制圖層的內(nèi)容尺铣。 (此技術(shù)最適合可能會周期性更改并可由外部對象(如視圖)提供的圖層內(nèi)容拴曲。)
  • 定義一個層子類并重寫其繪圖方法之一,以自己提供圖層內(nèi)容凛忿。 (如果您要創(chuàng)建自定義圖層子類澈灼,或者如果要更改圖層的基本繪圖行為,則此技術(shù)是合適的店溢。)

您唯一需要擔心為圖層提供內(nèi)容的時間是您自己創(chuàng)建圖層對象時叁熔。 如果您的應(yīng)用程序僅包含層次支持的視圖悼尾,則不必擔心使用上述任何技術(shù)來提供圖層內(nèi)容飒赃。 層次疊加的視圖可以以最有效的方式自動提供其相關(guān)層的內(nèi)容童漩。

1. Using an Image for the Layer’s Content - 使用圖像作為圖層的內(nèi)容

因為圖層只是用于管理位圖圖像的容器也颤,因此可以將圖像直接分配給圖層的內(nèi)容屬性埋虹。 為圖層分配圖像很容易缠局,您可以指定要在屏幕上顯示的確切圖像扎瓶。 該圖層使用您直接提供的圖像對象著蛙,并且不會嘗試創(chuàng)建該圖像的自己的副本。 如果您的應(yīng)用在多個地方使用相同的圖像册踩,這種行為可以節(jié)省內(nèi)存泳姐。

分配給圖層的圖像必須是CGImageRef類型暂吉。 (在OS X v10.6及更高版本中,還可以分配NSImage對象慕的。)分配圖像時阎肝,請記住提供其分辨率與本機設(shè)備分辨率相匹配的圖像肮街。 對于具有Retina顯示器的設(shè)備,這可能還需要您調(diào)整圖像的contentsScale屬性沛硅。 有關(guān)在圖層中使用高分辨率內(nèi)容的信息绕辖,請參閱Working with High-Resolution Images

2. Using a Delegate to Provide the Layer’s Content - 使用代理提供圖層的內(nèi)容

如果你的圖層的內(nèi)容围小,動態(tài)的改變肯适,需要時,你可以使用代理對象提供和更新內(nèi)容伴栓,展示時雨饺,圖層調(diào)用你的代理方法提供需要的內(nèi)容额港。

  • 如果您代理實現(xiàn)了displayLayer:方法,則該實現(xiàn)負責創(chuàng)建位圖并將其分配給圖層的內(nèi)容屬性肚医。
  • 如果您的委托實現(xiàn)了drawLayer:inContext:方法,Core Animation將創(chuàng)建一個位圖向瓷,創(chuàng)建一個圖形上下文來繪制該位圖猖任,然后調(diào)用代理方法來填充位圖。 所有您的代理方法都必須繪制到提供的圖形上下文中刁赖。

代理對象必須實現(xiàn)displayLayer:drawLayer:inContext:method宇弛。 如果代理同時實現(xiàn)displayLayer:drawLayer:inContext:method源请,則該層只調(diào)用displayLayer:方法谁尸。

重寫displayLayer:方法最適合當您的app想要加載或創(chuàng)建要顯示的位圖的情況症汹。下面代碼顯示了displayLayer:代理方法的示例實現(xiàn)贷腕。 在此示例中,代理使用幫助對象來加載和顯示所需的映像瞒斩。 代理方法根據(jù)自己的內(nèi)部狀態(tài)選擇要顯示的圖像胸囱,在該示例中是一個名為displayYesImage的自定義屬性烹笔。

//Setting the layer contents directly

- (void)displayLayer:(CALayer *)theLayer {
    // Check the value of some state property
    if (self.displayYesImage) {
        // Display the Yes image
        theLayer.contents = [someHelperObject loadStateYesImage];
    }
    else {
        // Display the No image
        theLayer.contents = [someHelperObject loadStateNoImage];
    }

如果您沒有預(yù)渲染圖像或幫助對象為您創(chuàng)建位圖,則您的代理可以使用drawLayer:inContext:方法動態(tài)繪制內(nèi)容饰豺。 下面代碼顯示了drawLayer:inContext:方法的示例實現(xiàn)冤吨。 在此示例中饶套,代理使用固定寬度和當前渲染顏色繪制簡單的曲線路徑妓蛮。

- (void)drawLayer:(CALayer *)theLayer inContext:(CGContextRef)theContext {
    CGMutablePathRef thePath = CGPathCreateMutable();
 
    CGPathMoveToPoint(thePath,NULL,15.0f,15.f);
    CGPathAddCurveToPoint(thePath,
                          NULL,
                          15.f,250.0f,
                          295.0f,250.0f,
                          295.0f,15.0f);
 
    CGContextBeginPath(theContext);
    CGContextAddPath(theContext, thePath);
 
    CGContextSetLineWidth(theContext, 5);
    CGContextStrokePath(theContext);
 
    // Release the path
    CFRelease(thePath);
}

對于具有自定義內(nèi)容的圖層支持的視圖蛤克,您應(yīng)該繼續(xù)重寫視圖的方法來執(zhí)行繪圖。 層次支持的視圖自動使其自身成為其層的委托翘簇,并實現(xiàn)所需的代理方法版保,您不應(yīng)該更改該配置夫否。 相反凰慈,您應(yīng)該實現(xiàn)您的視圖的drawRect:方法來繪制您的內(nèi)容。

OS X v10.8及更高版本中森篷,繪圖的另一種方法是通過重寫您的視圖的wantsUpdateLayerupdateLayer方法來提供位圖仲智。 重寫wantUpdateLayer并返回YES將使NSView類遵循備用渲染路徑钓辆。 而不是調(diào)用drawRect:,該視圖調(diào)用您的updateLayer方法功戚,其實現(xiàn)必須直接將位圖分配給圖層的內(nèi)容屬性疫铜。 這是AppKit希望直接設(shè)置視圖層對象的內(nèi)容的場景双谆。

3. Providing Layer Content Through Subclassing - 通過子類提供層內(nèi)容

如果您正在實現(xiàn)自定義層類顽馋,您可以重寫圖層類的繪圖方法來執(zhí)行任何繪圖。 層對象本身生成自定義內(nèi)容并不常見竟稳,但圖層肯定可以管理內(nèi)容的顯示他爸。 例如果善,CATiledLayer類通過將其分解成可以單獨管理和呈現(xiàn)的較小的圖塊來管理大型圖像巾陕。 因為只有圖層具有關(guān)于在任何給定時間需要渲染哪些瓦片的信息鄙煤,所以它直接管理繪圖行為。

當進行子類化時凉馆,您可以使用以下任一技術(shù)來繪制圖層的內(nèi)容:

  • 重寫圖層的display方法澜共,并使用它直接設(shè)置layer層的contents屬性。

  • 重寫圖層的drawInContext:方法植康,并使用它在圖形上下文中進行繪制。

您重寫的方法取決于在繪圖過程中需要多少控制存崖。display方法是更新圖層內(nèi)容的主要入口點睡毒,因此重寫該方法將使您完全控制該過程演顾。 重寫display方法也意味著您負責創(chuàng)建要分配給contents屬性的CGImageRef钠至。 如果您只想繪制內(nèi)容(或讓圖層管理繪圖操作),則可以重寫drawInContext:方法屿脐,讓圖層為您創(chuàng)建后備存儲的诵。

4. Tweaking the Content You Provide - 調(diào)整您提供的內(nèi)容

當您將圖像分配給圖層的內(nèi)容屬性時佑钾,圖層的contentsGravity屬性可確定如何處理該圖像以適應(yīng)當前邊界休溶。 默認情況下邮偎,如果圖像大于或小于當前邊界,則圖層對象將縮放圖像以適合可用空間豁跑。 如果圖層的寬高比不同于圖像的縱橫比艇拍,則可能導致圖像失真卸夕。 您可以使用contentsGravity屬性來確保您的內(nèi)容以最佳方式呈現(xiàn)。

您可以分配給contentGravity屬性的值分為兩類:

  • 基于位置的重力常數(shù)允許您將圖像固定到圖層邊界矩形的特定邊緣或角落贡羔,而不縮放圖像乖寒。
  • 基于比例的重力常數(shù)允許您使用幾個選項之一來拉伸圖像院溺,其中一些選項保留縱橫比珍逸,其中一些選項不保留谆膳。

下圖顯示了基于位置的重力設(shè)置如何影響圖像摹量。 除了kCAGravityCenter常數(shù)之外,每個常數(shù)將圖像引導到圖層邊界矩形的特定邊緣或角落凝果。 kCAGravityCenter常數(shù)將層中的圖像居中器净。 這些常量都不會導致以任何方式縮放圖像当凡,因此圖像始終以其原始大小呈現(xiàn)沿量。 如果圖像大于圖層的邊界朴则,則可能導致圖像的部分被剪切,如果圖像較小汹想,則圖層未被圖像覆蓋的部分如果設(shè)置則顯示圖層的背景顏色古掏。

下圖顯示了基于比例的重力常數(shù)如何影響圖像槽唾。 所有這些常數(shù)如果不完全符合層的邊界矩形夏漱,則縮放圖像挂绰。 模式之間的區(qū)別是它們?nèi)绾翁幚韴D像的原始寬高比服赎。 某些模式保留它重虑,而其他模式不保存缺厉。 默認情況下,圖層的contentGravity屬性設(shè)置為kCAGravityResize常量命爬,這是唯一不保留圖像寬高比的模式饲宛。

Scaling-based gravity constants for layers

5. Working with High-Resolution Images - 使用高分辨率圖像進行處理

層layer對底層設(shè)備屏幕的分辨率沒有固有的知識艇抠。 一個圖層簡單地存儲一個指向你的位圖的指針家淤,并以可用像素的最佳方式顯示它絮重。 如果將圖像分配給圖層的內(nèi)容屬性绿鸣,則必須通過將圖層的contentsScale屬性設(shè)置為適當?shù)闹祦砀嬷狢ore Animation關(guān)于圖像的分辨率。 屬性的默認值為1.0亮蛔,適用于要在標準分辨率屏幕上顯示的圖像究流。 如果您的圖像用于Retina顯示屏芬探,請將此屬性的值設(shè)置為2.0厘惦。

僅當您直接為圖層分配位圖時宵蕉,才需要更改contentsScale屬性的值羡玛。 UIKit和AppKit中的層次支持的視圖會根據(jù)屏幕分辨率和視圖管理的內(nèi)容自動將其圖層的比例因子設(shè)置為適當?shù)闹怠?例如稼稿,如果您將NSImage對象分配給OS X中的圖層的內(nèi)容屬性,則AppKit將查看是否存在圖像的標準和高分辨率變體敞恋。 如果有耳舅,AppKit將使用正確的變體作為當前分辨率浦徊,并設(shè)置contentScale屬性的值匹配盔性。

在OS X中呢岗,基于位置的重力常數(shù)影響從分配給該層的NSImage對象中選擇圖像表示的方式。 因為這些常量不會導致圖像被縮放突那,Core Animation依靠contentsScale屬性來選擇最合適的像素密度的圖像表示愕难。

在OS X中猫缭,圖層的委托可以實現(xiàn)圖層:shouldInheritContentsScale:fromWindow:方法壹店,并使用它來響應(yīng)比例因子的變化硅卢。 只要給定窗口的分辨率改變老赤,AppKit就會自動調(diào)用該方法抬旺,這可能是因為窗口在標準分辨率和高分辨率屏幕之間移動开财。 如果代理支持更改圖層的分辨率误褪,則此方法的實現(xiàn)應(yīng)返回YES兽间。 該方法應(yīng)該根據(jù)需要更新圖層的內(nèi)容以反映新的分辨率嘀略。


Adjusting a Layer’s Visual Style and Appearance - 調(diào)整圖層的視覺風格和外觀

圖層對象內(nèi)置有視覺裝飾帜羊,如邊框和背景顏色讼育,可用于補充圖層的主要內(nèi)容。 因為這些視覺裝飾不需要任何渲染饥瓷,所以它們可以在某些情況下使用層作為獨立實體呢铆。 所有您需要做的是在圖層上設(shè)置屬性刺洒,圖層處理必要的圖形逆航,包括任何動畫因俐。 有關(guān)這些視覺裝飾如何影響圖層外觀的其他說明抹剩,請參閱Layer Style Property Animations澳眷。

1. Layers Have Their Own Background and Border - layer有自己的背景和邊界

除了基于圖像的內(nèi)容之外钳踊,圖層還可以顯示填充的背景和繪制邊框拓瞪。 背景顏色呈現(xiàn)在圖層的內(nèi)容圖像之后,邊框呈現(xiàn)在該圖像的頂部面氓,如下圖所示舌界。 如果圖層包含子圖層禀横,它們也會顯示在邊框的下方柏锄。 因為背景顏色位于您的圖像后面趾娃,那種顏色會透過您圖像的任何透明部分抬闷,該顏色會透過圖像的任何透明部分笤成。

shows the code needed to set the background color and border for a layer. All of these properties are animatable
// Setting the background color and border of a layer

myLayer.backgroundColor = [NSColor greenColor].CGColor;
myLayer.borderColor = [NSColor blackColor].CGColor;
myLayer.borderWidth = 3.0;

注意:您可以使用任何類型的顏色作為圖層的背景炕泳,包括具有透明度或使用圖案圖像的顏色培遵。 當使用圖案圖像時籽腕,請注意皇耗,Core Graphics處理圖形圖像的渲染廊宪,并使用其與iOS中的默認坐標系不同的標準坐標系進行處理箭启。 因此蛉迹,在iOS上呈現(xiàn)的圖像默認顯示為顛倒傅寡,除非您翻轉(zhuǎn)坐標。

如果將圖層的背景顏色設(shè)置為不透明的顏色北救,請考慮將圖層的opaque屬性設(shè)置為YES荐操。 這樣做可以在屏幕上合成圖層時提高性能,并且不需要層的后備存儲來管理Alpha通道珍策。 但是托启,如果它也具有非零的角半徑攘宙,則不得將圖層標記為不透明屯耸。

2. Layers Support a Corner Radius - layer支持圓角

您可以通過向其添加角半徑來為圖層創(chuàng)建圓角矩形效果拐迁。 角半徑是一個視覺裝飾,可以掩蓋圖層邊界矩形的一部分角落疗绣,以允許底層內(nèi)容顯示线召,如圖2-4所示。 因為它涉及應(yīng)用透明度掩碼多矮,所以角度半徑不影響圖層內(nèi)容屬性中的圖像缓淹,除非將maskToBounds屬性設(shè)置為YES。 但是塔逃,角半徑始終會影響圖層的背景顏色和邊框的繪制方式讯壶。

A corner radius on a layer

要將角半徑應(yīng)用于圖層,請為圖層的cornerRadius屬性指定一個值湾盗。 您指定的半徑值以點為單位鹏溯,并在顯示之前應(yīng)用于圖層的所有四個角。

3. Layers Support Built-In Shadows - 圖層支持內(nèi)置陰影

CALayer類包括用于配置陰影效果的幾個屬性淹仑。 陰影通過使其看起來像浮動在其底層內(nèi)容上方丙挽,從而增加了圖層的深度。 這是另一種類型的視覺裝飾匀借,您可能會發(fā)現(xiàn)在您的應(yīng)用的特定情況下有用颜阐。 使用圖層,您可以控制陰影的顏色吓肋,相對于圖層的內(nèi)容凳怨,不透明度和形狀的位置。

默認情況下是鬼,層陰影的不透明度值設(shè)置為0肤舞,這有效地隱藏陰影。 將不透明度更改為非零值將導致Core Animation繪制陰影均蜜。 因為默認情況下李剖,陰影直接位于圖層之下,您可能還需要更改陰影的偏移量才能看到它囤耳。 重要的是要記住篙顺,您為陰影指定的偏移量是使用層的本機坐標系進行應(yīng)用的,這在iOS和OS X上是不同的充择。下圖顯示了一個陰影層向下延伸到 層的右邊 在iOS中德玫,這需要為y軸指定正值,但在OS X中椎麦,該值需要為負值宰僧。

當向圖層添加陰影時,陰影是圖層內(nèi)容的一部分观挎,但實際上會延伸到圖層的邊界矩形之外琴儿。 因此段化,如果您為圖層啟用masksToBounds屬性,陰影效果將圍繞邊緣進行裁剪凤类。 如果您的圖層包含任何透明的內(nèi)容穗泵,這可能會導致奇怪的影響,直接在圖層下方的陰影部分仍然可見谜疤,但超出圖層的部分不是佃延。 如果你想要一個陰影,但也想使用邊界掩蔽夷磕,你使用兩層而不是一層履肃。 將蒙版mask應(yīng)用于包含內(nèi)容的圖層,然后將該圖層嵌入到具有啟用陰影效果的完全相同大小的第二層中坐桩。

對于在layer中如何應(yīng)用陰影尺棋,可以參考 Shadow Properties

4. Filters Add Visual Effects to OS X Views

在OS X應(yīng)用程序中绵跷,您可以將Core Image過濾器直接應(yīng)用到圖層的內(nèi)容膘螟。 您可以這樣做來模糊或銳化圖層的內(nèi)容,更改顏色碾局,扭曲內(nèi)容或執(zhí)行許多其他類型的操作荆残。 例如,圖像處理程序可以使用這些濾波器非破壞性地修改圖像净当,而視頻編輯程序可能使用它們來實現(xiàn)不同類型的視頻轉(zhuǎn)換效果内斯。 并且因為過濾器以硬件應(yīng)用于圖層的內(nèi)容,渲染速度快像啼,流暢俘闯。

注意:在iOS中,你不能給layer對象添加濾波器忽冻。

對于給定的層真朗,您可以將過濾器應(yīng)用于圖層的前景和背景內(nèi)容。 前景內(nèi)容由圖層本身包含的所有內(nèi)容組成甚颂,包括其內(nèi)容屬性中的圖像蜜猾,其背景顏色,邊框及其子圖層的內(nèi)容振诬。 背景內(nèi)容是直接在圖層下的內(nèi)容,但實際上不是圖層本身的一部分衍菱。 大多數(shù)層的背景內(nèi)容是其直接上層的內(nèi)容赶么,其可以被層完全或部分地遮蔽。 例如脊串,當您希望用戶專注于圖層的前景內(nèi)容時辫呻,您可以對背景內(nèi)容應(yīng)用模糊濾鏡清钥。

您可以通過將CIFilter對象添加到圖層的以下屬性來指定過濾器:

  • filters屬性包含僅影響圖層前臺內(nèi)容的過濾器數(shù)組。
  • backgroundFilters屬性包含了影響layer背景內(nèi)容的一組濾波器放闺。
  • compositingFilter屬性定義了 foreground 和 background內(nèi)容是如何合成在一起的祟昭。

要向圖層添加過濾器,您必須先找到并創(chuàng)建CIFilter對象怖侦,然后在將其添加到圖層之前對其進行配置篡悟。 CIFilter類包括幾個類方法來定位可用的Core Image過濾器,例如filterWithName:方法匾寝。 創(chuàng)建過濾器只是第一步搬葬。 許多濾鏡具有定義濾鏡如何修改圖像的參數(shù)。 例如艳悔,框模糊濾鏡具有影響所應(yīng)用模糊量的輸入半徑參數(shù)急凰。 您應(yīng)該始終為這些參數(shù)提供值作為過濾器配置過程的一部分。 但是猜年,您不需要指定的一個常用參數(shù)是輸入圖像抡锈,它是由圖層本身提供的。

向圖層添加過濾器時乔外,最好在將過濾器添加到圖層之前配置過濾器參數(shù)床三。 這樣做的主要原因是一旦添加到圖層,就不能修改CIFilter對象本身袁稽。 但是勿璃,您可以使用圖層的setValue:forKeyPath:方法在事后更改過濾器值。

下面顯示了如何為層對象創(chuàng)建和應(yīng)用捏合失真過濾器推汽。 該過濾器向內(nèi)夾持層的源像素补疑,使最接近指定中心點的那些像素失真。 請注意歹撒,在示例中莲组,您不需要為濾鏡指定輸入圖像,因為圖層的圖像會自動使用暖夭。

//Applying a filter to a layer

CIFilter* aFilter = [CIFilter filterWithName:@"CIPinchDistortion"];

[aFilter setValue:[NSNumber numberWithFloat:500.0] forKey:@"inputRadius"];

[aFilter setValue:[NSNumber numberWithFloat:1.25] forKey:@"inputScale"];

[aFilter setValue:[CIVector vectorWithX:250.0 Y:150.0] forKey:@"inputCenter"];

myLayer.filters = [NSArray arrayWithObject:aFilter];

對于更多關(guān)于 Core Image filters,可以參考 Core Image Filter Reference迈着。


The Layer Redraw Policy for OS X Views Affects Performance - OS X視圖的圖層重繪策略會影響性能

在OS X中竭望,層次支持的視圖支持幾種不同的策略來確定何時更新底層的內(nèi)容。 因為本地AppKit繪圖模型與Core Animation引入的繪圖模型之間存在差異裕菠,所以這些策略可以將較舊的代碼遷移到Core Animation中更容易咬清。 您可以在逐個視圖的基礎(chǔ)上配置這些策略,以確保每個視圖的最佳性能。


Adding Custom Properties to a Layer - 圖層添加自定義屬性

CAAnimationCALayer類擴展了鍵值編碼約定以支持自定義屬性旧烧。 您可以使用此行為將數(shù)據(jù)添加到圖層影钉,并使用您定義的自定義鍵檢索它。 您甚至可以將操作與自定義屬性相關(guān)聯(lián)掘剪,以便在更改屬性時平委,將執(zhí)行相應(yīng)的動畫。

有關(guān)如何設(shè)置和獲取自定義屬性的信息夺谁,請參閱Key-Value Coding Compliant Container Classes廉赔。 有關(guān)向?qū)訉ο筇砑硬僮鞯男畔ⅲ垍㈤?a target="_blank" rel="nofollow">Changing a Layer’s Default Behavior予权。


Printing the Contents of a Layer-Backed View - 打印層支持的視圖內(nèi)容

在打印過程中昂勉,圖層根據(jù)需要重繪其內(nèi)容以適應(yīng)打印環(huán)境。 而核心動畫通常在渲染到屏幕時依賴于緩存的位圖扫腺,當打印時它會重繪該內(nèi)容岗照。 特別是,如果層支持的視圖使用drawRect:方法來提供圖層內(nèi)容笆环,Core Animation會在打印期間再次調(diào)用drawRect:生成打印圖層內(nèi)容攒至。

后記

未完,待續(xù)~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末躁劣,一起剝皮案震驚了整個濱河市迫吐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌账忘,老刑警劉巖志膀,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鳖擒,居然都是意外死亡溉浙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門蒋荚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戳稽,“玉大人,你說我怎么就攤上這事期升【妫” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵播赁,是天一觀的道長颂郎。 經(jīng)常有香客問我,道長容为,這世上最難降的妖魔是什么祖秒? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任诞吱,我火速辦了婚禮舟奠,結(jié)果婚禮上竭缝,老公的妹妹穿的比我還像新娘。我一直安慰自己沼瘫,他們只是感情好抬纸,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耿戚,像睡著了一般湿故。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上膜蛔,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天坛猪,我揣著相機與錄音,去河邊找鬼皂股。 笑死墅茉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的呜呐。 我是一名探鬼主播就斤,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蘑辑!你這毒婦竟也來了洋机?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤洋魂,失蹤者是張志新(化名)和其女友劉穎绷旗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體副砍,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡衔肢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了址晕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膀懈。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谨垃,靈堂內(nèi)的尸體忽然破棺而出启搂,到底是詐尸還是另有隱情,我是刑警寧澤刘陶,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布胳赌,位于F島的核電站,受9級特大地震影響匙隔,放射性物質(zhì)發(fā)生泄漏疑苫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捍掺。 院中可真熱鬧撼短,春花似錦、人聲如沸挺勿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽不瓶。三九已至禾嫉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚊丐,已是汗流浹背熙参。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留麦备,地道東北人孽椰。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像泥兰,于是被迫代替她去往敵國和親弄屡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容