[譯] Animating text layers using CoreAnimation and CoreText frameworks in iOS SDK

原文地址: Animating text layers using CoreAnimation and CoreText frameworks in iOS SDK


4月13號 使用iOS SDK中的CoreAnimation和CoreText實現文本層動畫

CoreAnimation是一個非常強大的框架。通過使用CABasicAnimationCAKeyFrameAnimation或者CAAnimationGroup,我們可以創建驚豔的用戶體驗來,同時基本上是沒有什麼限制的。僅僅取決於我們想要在屏幕上展示什麼和它是怎麼交互的。事實證明,CoreAnimation也可以和一些其他的框架(如CoreGraphics或者CoreText)組合使用,這也給了開發者創造更加驚豔的動畫的能力。使用CoreTextCoreAnimation我們可以給任何指定字體類型和字體大小的文本添加動畫。在這篇文章中我會展示一種方式如何做到這樣。

CoreText基礎

首先,讓我向大家展示一下CoreText的基礎。爲了給文本添加動畫,我們必須知道線條(line)和象形符號(glyph)是什麼,這會幫助我們理解從一個文本生成一條路徑(path)的整個過程。蘋果已經爲我們奠定了CoreText的基礎知識。所有的這些都可以在下面看到。下面是我收集的最重要的信息。


在此層次結構的頂部是frame setter對象。帶有屬性的字符串和圖形路徑作爲輸入。一個frame setter生成文本的一個或者多個frame。每一個frame對象都代表一個段落。要生成frameframe setter調用一個typesetter對象。當一個frame setter奠定一個特定的frame的時候,它適用於段落樣式,包括對齊方式,製表位,或者行距等屬性。typesetter將這些帶有屬性的字符串中的字符轉換成象形字符(glyphs),同時也適合那些象形字符(glyphs)形成填充文字框的線條。

每一個frame對象包含段落的線對象,它代表一個段落中文本的一行。一個frame對象可能只包含一個單一的長line對象,也可能包含一系列的line。line對象在frame設置時期被typesetter創建。每一個line對象包含一組象形字符運行(glyph run)對象。一個象形字符運行(glyph run)是一組共享相同屬性和方向的連續象形字符(glyph)。typesetter創建象形字符運行(glyph run)就像它從字符串、屬性和字體對象生產line一樣。這意味着,一個line構成一個或者多個象形字符運行(glyph run)。在層次結構的尾部是通常代表單個文本字符的象形字符(glyph)對象。經過我們對CoreText的基本熟悉,我們現在可以文本層動畫了。

Animating text layer

爲了給文本層添加動畫,我們需要將其轉換成CGPath對象。首先我們必須創建我們想要添加動畫的帶屬性的字符,然後我們爲了得到象形字符運行(glyph run)不得不從這個字符串中創建一個line對象。下面的代碼展示了我們如何實現這些目的:

let attrString  = NSAttributedString(string: text, attributes: [kCTFontAttributeName as String : font])
let line        = CTLineCreateWithAttributedString(attrString)
let runArray    = CTLineGetGlyphRuns(line)

這裏我們將所有的象形字符運行(glyph run)保存在runArray中。我們通過這個數組循環,並且從每一個象形字符運行(glyph run)來看,我們可以得到這些字體,以及所有相應的象形字符(glyph)。現在我們可以通過遍歷所有的象形字符(glyph)來選出特定的象形字符(glyph)對象。當我們有了這個對象,我們可以計算它的位置,並使用CTFontCreatePathForGlyph函數將其轉換成path對象。通過擁有一個路徑就知道它的位置,我們就可以創建一個有象形字符(glyph)路徑組合而成的總體路徑。下面的僞代碼顯示了整體算法:

%For each glyph run
for runIndex in 0..<CFArrayGetCount(runArray) {
     let runFont = %Get a font from a single glyph

     %For each glyph in a single glyph run
     for runGlyphIndex in 0..<CTRunGetGlyphCount(run) {
                var glyph    = %Get a glyph
                var position = %Get glyph’s position

                %Get a letter path from a single glyph
                let letter = CTFontCreatePathForGlyph(runFont, glyph, nil)
                 %Make a translation to a desired position
                var t = CGAffineTransformMakeTranslation(position.x, position.y)
                 %Add a single letter path to the whole path  
                CGPathAddPath(letters, &t, letter)
            }
     }

之後我們已經將我們的文本轉換成path對象,並將其添加到路徑層,我們就可以使用下面代碼簡單添加動畫了:

let pathAnimation       = CABasicAnimation(keyPath: "strokeEnd")
pathAnimation.duration  = duration
pathAnimation.fromValue = 0.0
pathAnimation.toValue   = 1.0
pathAnimation.delegate  = self
pathLayer?.addAnimation(pathAnimation, forKey: "strokeEnd")

爲了達到給文本層添加動畫的目的,一個VRMTextAnimator類被創建了。這個類和示範文本層動畫的示例工程在這裏可以找到。

爲了使用這個類,你不得不使用帶有一個reference view的初始化方式init(referenceView:)``初始化。reference view是一種類型的視圖,其中我們執行文本動畫。VRMTextAnimator有兩個關鍵屬性,animationLayerpathLayer。第一個是我們要執行動畫的CALayer對象,第二個是CAShapeLayer對象,它存儲從我們之前設定的文字創造了一個CGPath對象。這個類也有三個可設置的屬性:字體名稱/fontName,字體尺寸/fontSizetextToAnimate。如果我們想要動畫一個特定的文本與他的字體和字體大小,我們需要設置這些屬性,VRMTextAnimator`也有一個代理對象,可以通知我們動畫的起點和終點。


在這個項目中,有兩種類型的文本層動畫。第一種動畫是簡單的開始按鈕觸發的,第二種是通過滑塊控制的。事實證明,我們可以設置它的speedfromValuetoValuedurationtimeOffset屬性。如果我們設置fromValue爲0,toValue爲1,duration爲1,同時我們正在動畫pathLayer對象的strokeEnd屬性,我們就可以通過設置pathLayertimeOffset屬性來繪製文本輪廓的相應部分。



文/上天遁地(簡書作者)
原文鏈接:http://www.jianshu.com/p/1780bb27ce8f
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。
發佈了46 篇原創文章 · 獲贊 9 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章