はじめに
弊社のアプリ開発では、アニメーションの実装にLottieを利用する機会が増えてきました。複雑なアニメーションも手軽に実装でき、マルチプラットフォームでの展開も容易なので、利用されている方も多くいらっしゃるのではないでしょうか。
今回の記事では、UIKitベースで作成されている Lottie SDK を SwiftUI で利用するための手順を紹介してみようと思います。
開発環境
今回の記事は、以下の環境で動作確認を行なっております。
- macOS 12.0.1
- iOS 15.0 (simulator)
- Xcode 13.1
プロジェクト準備
SwiftUIを利用したiOSアプリプロジェクトを新規で作成し、Swift Package Manager 経由で Lottie iOS SDK を組み込みました。

アニメーションファイルを用意
Lottie で利用するアニメーションファイルは、LottieFiles というサイトで入手可能です。会員登録(無料)が必要ですが、数多くのアニメーション素材をダウンロードすることが可能です。
今回はこのサイトからCat Loaderというアニメーション素材を利用させてもらうことにします。右上にあるメニューから Lottie JSON を選択して、jsonファイルをダウンロードしてください。

ダウンロードしたjsonファイルは、任意の名前に変更してXcodeプロジェクトに組み込みます。今回は cat.json というファイル名にしました。

アニメーション用のViewを作成
次に、Lottieのアニメーションファイルを使ったアニメーション用のViewを作成します。UIKitベースのSDKを利用するため、UIViewRepresentableを実装し、以下のように作成しました。
import SwiftUI
import Lottie
struct LottieView: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = AnimationView(name: "cat")
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
こちらをContentViewから読み込んでみます。
import SwiftUI
struct ContentView: View {
var body: some View {
LottieView()
}
}

表示されましたが、サイズが合っていないのでサイズを調整します。
import SwiftUI
struct ContentView: View {
var body: some View {
LottieView()
.frame(width: 200, height: 200) // サイズを指定.
}
}

どうやら frame() が効いていないようです。LottieView のサイズは200 * 200になっているのですが、肝心のAnimationViewがLottieViewをはみ出してしまっています。
そのため、LottieViewを以下のように修正します。UIViewを親として用意し、AnimationViewをaddSubView()します。その際に、AutoLayoutで親ビューのサイズに合わせるようにします。
func makeUIView(context: Context) -> UIView {
let view = AnimationView(name: "cat")
view.translatesAutoresizingMaskIntoConstraints = false
// 親ビューを用意し、AnimationViewをサブビューにする.
let parentView = UIView()
parentView.addSubview(view)
parentView.addConstraints([
view.widthAnchor.constraint(equalTo: parentView.widthAnchor),
view.heightAnchor.constraint(equalTo: parentView.heightAnchor)
])
return parentView
}
これで frame() を用いたサイズ指定が可能になりました。

アニメーションさせる
では実際にアニメーションさせてみましょう。LottieViewにアニメーションの状態を管理するプロパティ isPlay を追加し、この状態に合わせてアニメーションのON/OFFを切り替えるようにします。
ContentViewには、この状態を切り替えるためのToggleスイッチを用意しました。
@Binding var isPlay: Bool // アニメーションの状態管理.
func updateUIView(_ uiView: UIView, context: Context) {
// AnimationViewを取得.
guard let view = uiView.subviews.compactMap({ $0 as? AnimationView }).first else { return }
if isPlay {
// すでにアニメーション中なら何もしない.
if view.isAnimationPlaying { return }
// アニメーション開始.
view.play { _ in
// 終わったら状態をOFFにする.
isPlay = false
}
} else {
// アニメーションを一時停止.
view.pause()
}
}
struct ContentView: View {
@State private var isPlay = false // アニメーションの状態管理
var body: some View {
VStack {
LottieView(isPlay: $isPlay)
.frame(width: 200, height: 200)
Toggle("アニメーション", isOn: $isPlay)
}
.padding()
}
}
ToggleをONにするとアニメーションを開始し、終了するとToggleもOFFになります。アニメーションの途中でToggleを操作することも可能です。
アニメーションをループさせる
次に、アニメーションのループ設定を切り替えられるようにします。ループ設定の状態管理を行うためのBoolプロパティを追加し、Toggleで切り替えられるようにしました。
@Binding var isPlay: Bool // アニメーションの状態管理.
@Binding var isLoop: Bool // ループ設定の状態管理.
func updateUIView(_ uiView: UIView, context: Context) {
// AnimationViewを取得.
guard let view = uiView.subviews.compactMap({ $0 as? AnimationView }).first else { return }
// ループ状態によってloopModeを切り替える.
view.loopMode = isLoop ? .loop : .playOnce
// 省略.
}
struct ContentView: View {
@State private var isPlay = false // アニメーションの状態管理.
@State private var isLoop = false // ループ設定の状態管理.
var body: some View {
VStack {
LottieView(isPlay: $isPlay, isLoop: $isLoop)
.frame(width: 200, height: 200)
Toggle("アニメーション", isOn: $isPlay)
Toggle("ループ", isOn: $isLoop)
}
.padding()
}
}
ループ設定がONの場合はアニメーションを続けるようになりました。ループ設定がOFFの場合は、そのアニメーションが終わったら終了します。
最後に
いかがだったでしょうか。Lottieはやはり優秀なアニメーションライブラリですね。
今後はSwiftUIを利用した開発も少しずつ増えてくるでしょうが、UIKitベースのライブラリもまだまだたくさんあります。こういった使い方を把握し、SwiftUIが盛り上がってくるといいですね!