原文地址: Animating text layers using CoreAnimation and CoreText frameworks in iOS SDK
4月13號 使用iOS SDK中的CoreAnimation和CoreText實現文本層動畫
CoreAnimation
是一個非常強大的框架。通過使用CABasicAnimation
,CAKeyFrameAnimation
或者CAAnimationGroup
,我們可以創建驚豔的用戶體驗來,同時基本上是沒有什麼限制的。僅僅取決於我們想要在屏幕上展示什麼和它是怎麼交互的。事實證明,CoreAnimation
也可以和一些其他的框架(如CoreGraphics
或者CoreText
)組合使用,這也給了開發者創造更加驚豔的動畫的能力。使用CoreText
和CoreAnimation
我們可以給任何指定字體類型和字體大小的文本添加動畫。在這篇文章中我會展示一種方式如何做到這樣。
CoreText基礎
首先,讓我向大家展示一下CoreText
的基礎。爲了給文本添加動畫,我們必須知道線條(line
)和象形符號(glyph
)是什麼,這會幫助我們理解從一個文本生成一條路徑(path)的整個過程。蘋果已經爲我們奠定了CoreText
的基礎知識。所有的這些都可以在下面看到。下面是我收集的最重要的信息。
在此層次結構的頂部是frame setter
對象。帶有屬性的字符串和圖形路徑作爲輸入。一個frame setter
生成文本的一個或者多個frame
。每一個frame對象都代表一個段落。要生成frame
,frame 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有兩個關鍵屬性,
animationLayer和
pathLayer。第一個是我們要執行動畫的CALayer對象,第二個是CAShapeLayer對象,它存儲從我們之前設定的文字創造了一個
CGPath對象。這個類也有三個可設置的屬性:字體名稱/
fontName,字體尺寸/
fontSize,
textToAnimate。如果我們想要動畫一個特定的文本與他的字體和字體大小,我們需要設置這些屬性,
VRMTextAnimator`也有一個代理對象,可以通知我們動畫的起點和終點。
在這個項目中,有兩種類型的文本層動畫。第一種動畫是簡單的開始按鈕觸發的,第二種是通過滑塊控制的。事實證明,我們可以設置它的speed
,fromValue
,toValue
,duration
和timeOffset
屬性。如果我們設置fromValue
爲0,toValue
爲1,duration
爲1,同時我們正在動畫pathLayer對象的strokeEnd
屬性,我們就可以通過設置pathLayer
的timeOffset
屬性來繪製文本輪廓的相應部分。
原文鏈接:http://www.jianshu.com/p/1780bb27ce8f
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。