呈現與模型(隱式動畫)

来源:http://www.cnblogs.com/EchoHG/archive/2017/10/04/7625560.html
-Advertisement-
Play Games

呈現與模型 CALayer的屬性行為其實很不正常,因為改變一個圖層的屬性並沒有立刻生效,而是通過一段時間漸變更新。這是怎麼做到的呢? 當你改變一個圖層的屬性,屬性值的確是立刻更新的(如果你讀取它的數據,你會發現它的值在你設置它的那一刻就已經生效了),但是屏幕上並沒有馬上發生改變。這是因為你設置的屬性 ...


呈現與模型

CALayer的屬性行為其實很不正常,因為改變一個圖層的屬性並沒有立刻生效,而是通過一段時間漸變更新。這是怎麼做到的呢?

當你改變一個圖層的屬性,屬性值的確是立刻更新的(如果你讀取它的數據,你會發現它的值在你設置它的那一刻就已經生效了),但是屏幕上並沒有馬上發生改變。這是因為你設置的屬性並沒有直接調整圖層的外觀,相反,他只是定義了圖層動畫結束之後將要變化的外觀。

當設置CALayer的屬性,實際上是在定義當前事務結束之後圖層如何顯示的模型。Core Animation扮演了一個控制器的角色,並且負責根據圖層行為和事務設置去不斷更新視圖的這些屬性在屏幕上的狀態。

我們討論的就是一個典型的微型MVC模式CALayer是一個連接用戶界面(就是MVC中的view)虛構的類,但是在界面本身這個場景下,CALayer的行為更像是存儲了視圖如何顯示和動畫的數據模型。實際上,在蘋果自己的文檔中,圖層樹通常都是值的圖層樹模型。

在iOS中,屏幕每秒鐘重繪60次。如果動畫時長比60分之一秒要長,Core Animation就需要在設置一次新值和新值生效之間,對屏幕上的圖層進行重新組織。這意味著CALayer除了“真實”值(就是你設置的值)之外,必須要知道當前顯示在屏幕上的屬性值的記錄。

每個圖層屬性的顯示值都被存儲在一個叫做呈現圖層的獨立圖層當中,他可以通過-presentationLayer方法來訪問。這個呈現圖層實際上是模型圖層的複製,但是它的屬性值代表了在任何指定時刻當前外觀效果。換句話說,你可以通過呈現圖層的值來獲取當前屏幕上真正顯示出來的值(圖7.4)。

我們在第一章中提到除了圖層樹,另外還有呈現樹。呈現樹通過圖層樹中所有圖層的呈現圖層所形成。註意呈現圖層僅僅當圖層首次被提交(就是首次第一次在屏幕上顯示)的時候創建,所以在那之前調用-presentationLayer將會返回nil

你可能註意到有一個叫做–modelLayer的方法。在呈現圖層上調用–modelLayer將會返回它正在呈現所依賴的CALayer。通常在一個圖層上調用-modelLayer會返回–self(實際上我們已經創建的原始圖層就是一種數據模型)。

圖7.4

圖7.4 一個移動的圖層是如何通過數據模型呈現的

大多數情況下,你不需要直接訪問呈現圖層,你可以通過和模型圖層的交互,來讓Core Animation更新顯示。兩種情況下呈現圖層會變得很有用,一個是同步動畫,一個是處理用戶交互。

  • 如果你在實現一個基於定時器的動畫(見第11章“基於定時器的動畫”),而不僅僅是基於事務的動畫,這個時候準確地知道在某一時刻圖層顯示在什麼位置就會對正確擺放圖層很有用了。
  • 如果你想讓你做動畫的圖層響應用戶輸入,你可以使用-hitTest:方法(見第三章“圖層幾何學”)來判斷指定圖層是否被觸摸,這時候對呈現圖層而不是模型圖層調用-hitTest:會顯得更有意義,因為呈現圖層代表了用戶當前看到的圖層位置,而不是當前動畫結束之後的位置。

我們可以用一個簡單的案例來證明後者(見清單7.7)。在這個例子中,點擊屏幕上的任意位置將會讓圖層平移到那裡。點擊圖層本身可以隨機改變它的顏色。我們通過對呈現圖層調用-hitTest:來判斷是否被點擊。

如果修改代碼讓-hitTest:直接作用於colorLayer而不是呈現圖層,你會發現當圖層移動的時候它並不能正確顯示。這時候你就需要點擊圖層將要移動到的位置而不是圖層本身來響應點擊(這就是為什麼用呈現圖層來響應交互的原因)。

清單7.7 使用presentationLayer圖層來判斷當前圖層位置

 1 @interface ViewController ()
 2 
 3 @property (nonatomic, strong) CALayer *colorLayer;
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad
10 {
11     [super viewDidLoad];
12     //create a red layer
13     self.colorLayer = [CALayer layer];
14     self.colorLayer.frame = CGRectMake(0, 0, 100, 100);
15     self.colorLayer.position = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
16     self.colorLayer.backgroundColor = [UIColor redColor].CGColor;
17     [self.view.layer addSublayer:self.colorLayer];
18 }
19 
20 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
21 {
22     //get the touch point
23     CGPoint point = [[touches anyObject] locationInView:self.view];
24     //check if we've tapped the moving layer
25     if ([self.colorLayer.presentationLayer hitTest:point]) {
26         //randomize the layer background color
27         CGFloat red = arc4random() / (CGFloat)INT_MAX;
28         CGFloat green = arc4random() / (CGFloat)INT_MAX;
29         CGFloat blue = arc4random() / (CGFloat)INT_MAX;
30         self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
31     } else {
32         //otherwise (slowly) move the layer to new position
33         [CATransaction begin];
34         [CATransaction setAnimationDuration:4.0];
35         self.colorLayer.position = point;
36         [CATransaction commit];
37     }
38 }
39 @end
40 
41  
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 物理模擬 即使使用了基於定時器的動畫來複制第10章中關鍵幀的行為,但還是會有一些本質上的區別:在關鍵幀的實現中,我們提前計算了所有幀,但是在新的解決方案中,我們實際上實在按需要在計算。意義在於我們可以根據用戶輸入實時修改動畫的邏輯,或者和別的實時動畫系統例如物理引擎進行整合。 Chipmunk 我們 ...
  • 自定義緩衝函數 在第八章中,我們給時鐘項目添加了動畫。看起來很贊,但是如果有合適的緩衝函數就更好了。在顯示世界中,鐘錶指針轉動的時候,通常起步很慢,然後迅速啪地一聲,最後緩衝到終點。但是標準的緩衝函數在這裡每一個適合它,那該如何創建一個新的呢? 除了+functionWithName:之外,CAMe ...
  • 直接寫解決方法吧: 1、將XML里的靜態引入刪除: 2、在代碼里 findViewById 找到 NavigationView,然後引入 Header 和 Menu,再獲取頭部佈局,最後設置監聽事件: 3、完整代碼如下: ...
  • 動畫速度 動畫實際上就是一段時間內的變化,這就暗示了變化一定是隨著某個特定的速率進行。速率由以下公式計算而來: 這裡的變化可以指的是一個物體移動的距離,時間指動畫持續的時長,用這樣的一個移動可以更加形象的描述(比如position和bounds屬性的動畫),但實際上它應用於任意可以做動畫的屬性(比如 ...
  • #CAMediaTiming`協議 CAMediaTiming協議定義了在一段動畫內用來控制逝去時間的屬性的集合,CALayer和CAAnimation都實現了這個協議,所以時間可以被任意基於一個圖層或者一段動畫的類控制。 持續和重覆 我們在第八章“顯式動畫”中簡單提到過duration(CAMed ...
  • 在動畫過程中取消動畫 之前提到過,你可以用-addAnimation:forKey:方法中的key參數來在添加動畫之後檢索一個動畫,使用如下方法: 但並不支持在動畫運行過程中修改動畫,所以這個方法主要用來檢測動畫的屬性,或者判斷它是否被添加到當前圖層中。 為了終止一個指定的動畫,你可以用如下方法把它 ...
  • Feature: 點擊選擇拍照或者打開相冊,選取圖片進行裁剪最後設置為圓形頭像。 Problem: 拍好照片,點擊裁剪,彈Toast“無法載入此圖片”。 Solution: 在裁剪的class裡加兩行代碼 主要代碼如下: ...
  • 屬性動畫 CAAnimationDelegate在任何頭文件中都找不到,但是可以在CAAnimation頭文件或者蘋果開發者文檔中找到相關函數。在這個例子中,我們用-animationDidStop:finished:方法在動畫結束之後來更新圖層的backgroundColor。 當更新屬性的時候, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...