-
Notifications
You must be signed in to change notification settings - Fork 0
Text Animation
Song edited this page Aug 4, 2021
·
6 revisions
by Song
- 다른 View 변경으로 인해 멈추지 않는 애니메이션 구현
- Main Thread 외의 Thread 활용
기존 사용하던 GhostTypeWriter 라이브러리는 Main Thread에서 실행됨
- 콜렉션 뷰 스크롤 시 멈추어 개선 필요
- CATextLayer를 활용하여 Custom하게 제작
- UIView를 subclassing한 TypeWriterView에 CATextLayer를 활용한 애니메이션 메소드 구현
- 각 글자마다 타이머 딜레이를 다르게 주어 1글자씩 나타나게 함
func startTyping(text fullText: String, duration: Double) {
let totalCount = fullText.count
let delayPerLetter = duration / Double(totalCount)
let letters = fullText.map { String($0) }
for count in 0..<totalCount {
let currentDelay = delayPerLetter * Double(count)
Timer.scheduledTimer(withTimeInterval: currentDelay, repeats: false) { [weak self] _ in
self?.changeText(for: count, with: letters)
}
}
}
private func changeText(for count: Int, with letters: [String]) {
let currentText = text(for: count, with: letters)
textLayer.string = currentText
}
private func text(for currentCount: Int, with letters: [String]) -> String {
return (0...currentCount).map { letters[$0] }.joined()
}- CATextLayer를 View의 중앙에 위치시키는 메소드 구현
func startTyping(text fullText: String, duration: Double) {
adjustFrameToCenter(for: fullText)
// 애니메이션 코드 생략
}
private func adjustFrameToCenter(for fullText: String) {
let lineCount = fullText.components(separatedBy: "\n").count
let fontHeight = font.capHeight
let totalTextHeight = fontHeight * CGFloat(lineCount)
let yOffset = (layer.bounds.size.height-totalTextHeight*1.5)/2 // Position이 아닌 Origin이기 때문에 전체 텍스트 높이의 반만큼 더 위로 올려 줌
textLayer.frame = textLayer.frame.offsetBy(dx: 0, dy: yOffset)
}결과
- CATextLayer의 String Property는 Animatable하지 않다
- 따라서, Layer의 텍스트 변경을 위해서는 Main Thread를 거쳐갈 수밖에 없음
애니메이션과 동시에 유저 인터랙션이 발생할 가능성이 있는 ItemViewController에 한해 Animatable한 속성을 활용한 것으로 변경
created by 우송