はじめに
テキストを滑らかに変化させるアニメーションを作る方法を紹介します。
作るもの
このようなテキストのアニメーションを作ります。
やり方
コード
import SwiftUI
struct AnimatedText: View {
let text: String
// テキストの各文字と、その文字のIDを格納します。
@State private var characters: [(character: String.Element, id: String)] = []
// matchedGeometryEffectを用いたアニメーションを行うために必要な変数です。
@Namespace private var namespace
var body: some View {
HStack(spacing: 0) {
// charactersをForEachで回します。
ForEach(characters, id: \.id) { character, id in
// Textを表示します。matchedGeometryEffectのidに、charactersのidを指定します。
Text(String(character))
.frame(height: .zero)
.matchedGeometryEffect(id: id, in: namespace)
}
}
.animation(.easeIn(duration: 0.3), value: characters.map(\.character)) // アニメーションを設定します。
.onAppear {
setCharacters(text: text)
}
.onChange(of: text) { newValue in
setCharacters(text: newValue)
}
}
private func setCharacters(text: String) {
// 文字列を文字に分割します。
var oldCharacters = characters
var newCharacters: [(character: String.Element, id: String)] = []
for character in text {
if let oldCharacter = oldCharacters.first(where: { $0.character == character }) {
// characterがoldCharactersに含まれている場合は、oldCharacterのidを指定してnewCharactersに追加します。
newCharacters.append((character: character, id: oldCharacter.id))
// oldCharactersからoldCharacterを削除します。
if let index = oldCharacters.firstIndex(where: { $0.character == character }) {
oldCharacters.remove(at: index)
}
} else {
// characterがoldCharactersに含まれていない場合は、新しいidを指定してnewCharactersに追加します。
let id = UUID().uuidString
newCharacters.append((character: character, id: id))
}
}
characters = newCharacters
}
}
使い方
import SwiftUI
struct ContentView: View {
private let texts: [String] = [
"しりとり",
"りんご",
"ごりら",
"らっぱ",
"ぱんだ",
"だり",
]
@State private var selectedIndex = 0
var body: some View {
VStack(spacing: 60) {
AnimatedText(text: texts[selectedIndex])
.font(.system(size: 48).bold())
.padding()
Button("Change") {
if selectedIndex == texts.count - 1 {
selectedIndex = 0
} else {
selectedIndex += 1
}
}
.buttonStyle(.bordered)
}
}
}
まとめ
matchedGeometryEffectを用いることで、滑らかに変化するViewを作ることができます。今回は、文字列を文字に分割して、それぞれの文字にidを割り当てることで、テキストの滑らかなアニメーションを実現しました。
使用例
このテクニックを使った例です。