【SwiftUI】Lottieでアニメーションを表示する

# Lottieとは
![](https://github.com/airbnb/lottie-ios/raw/master/_Gifs/Examples1.gif)

https://github.com/airbnb/lottie-ios

簡単にアニメーションを表示できるライブラリです
[こちら](https://lottiefiles.com/featured)で公開されているアニメーションがすぐ使えるようになります。
そしてとても軽いので使いやすいです。

# インストール
- CocoaPods
- Carthage
- Swift Package Manager

上記3つがサポートされています。

今回はSwift Package Managerでインストールしていきます。

①: [lottie-ios](https://github.com/airbnb/lottie-ios)のURLをコピー
![スクリーンショット 2022-05-07 15.06.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ebdf2dc3-754b-6382-ce48-3287a423abe7.png)
②: Xcodeのメニューバーの「File」を選択
![スクリーンショット 2022-05-07 15.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7a84e170-12a7-b2f6-ef2f-0291670921ad.png)
③: 「Add Packages...」を選択
<img width="40%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1d6f4a3c-e8f1-5af2-7086-98b44b96471d.png">
④: ①でコピーしたURLを貼り付ける
⑤: 「Add Package」を選択
![スクリーンショット 2022-05-07 15.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/13fe9b6f-4f10-ab64-054a-7570a441b683.png)
⑥: 「Add Package」を選択
![スクリーンショット 2022-05-07 15.15.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b2c955ac-b356-7998-2e58-836d08758687.png)

# 使い方
[こちら](https://lottiefiles.com/81333-github)のアニメーションをサンプルとして使用しますのでダウンロードしてください。
<img width="48%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/457fd761-219e-eb4d-e91c-263d334254e8.png"> <img width="48%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0ecb9f34-d4d4-7adf-31ab-1a8bedca0a3f.png"> 

ダウンロードしたファイルをXcodeにドラッグします。
<img width="48%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ec09a04c-e39b-1a3e-164a-9e2a1c460d00.png"> <img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/84b34168-a706-c2c8-1bde-a43be022f86a.png">

```LottieView.swift
import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    var name: String
    var animationView = AnimationView()
    func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
        let view = UIView(frame: .zero)
        // 表示したいアニメーションのファイル名
        animationView.animation = Animation.named(name)
        // 比率
        animationView.contentMode = .scaleAspectFit
        // ループモード
        animationView.loopMode = .loop
        animationView.play()
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        NSLayoutConstraint.activate([
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
        return view
    }
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
    }
}
```
```ContentView.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        LottieView(name: "81333-github")
    }
}
```
<img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4459f5c2-6225-a934-896b-e254cdbce8e6.gif">

完成〜！！！と言いたいところですがダークモードにしてみてください

真っ黒になってしまってる。。。。

そうなんです。
このアニメーション自体が黒いのでダークモードにすると見えなくなってしまうのです。

# ダークモードに対応する
![IMG_0202.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/cde7adba-76ec-0c1d-17fa-29711fd0bd65.jpeg)
色を変更しなければならない箇所が2箇所あります。
これを特定する作業に入ります。

LottieViewにこちらを追加していきます。
```Swift
// アニメーションのlogを表示
animationView.logHierarchyKeypaths()
```

```LottieView.Swift
import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    var name: String
    var animationView = AnimationView()
    func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
        // 省略...
        animationView.loopMode = .loop

        // アニメーションのログを表示
        animationView.logHierarchyKeypaths()

        animationView.play()
        // 省略...
    }
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
    }
}
```
このようなログが表示されるはずです
<img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/41514984-bb68-13ba-0c49-e77542314476.png">

ここの中から先ほどの2箇所を特定します。

ログの中から「Color」という単語を探します。
<img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4af00f9f-6997-e40e-6387-f0f5df32ce37.png"> <img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b49fcc2f-e603-0145-09f7-593122681155.png">
2箇所発見することができました。
おそらくこの2箇所であると推測できます。

変更してみる
こちらをLottieViewに追加します。
```Swift
// ライトモード時のLittieの色
let lightmode = Color(r: 0, g: 0, b: 0, a: 1)
// ダークモード時のLittieの色
let darkmode = Color(r: 1, g: 1, b: 1, a: 1)
// 色をセットする
let ColorValueProvider = ColorValueProvider(colorScheme == .dark ? darkmode : lightmode)
// パスを取得
let strokePath = AnimationKeypath(keypath: "BG.Stroke 1.Color")
let logoPath = AnimationKeypath(keypath: "logo.Group 1.Fill 1.Color")
// 色を適用
animationView.setValueProvider(ColorValueProvider, keypath: strokePath)
animationView.setValueProvider(ColorValueProvider, keypath: logoPath)
```

```LottieView.swift
import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    var name: String
    var animationView = AnimationView()
    // ダークモード検知
    @Environment(\.colorScheme) var colorScheme
    func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
        let view = UIView(frame: .zero)
        animationView.animation = Animation.named(name)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.logHierarchyKeypaths()

        // ライトモード時のLittieの色
        let lightmode = Color(r: 0, g: 0, b: 0, a: 1)
        // ダークモード時のLittieの色
        let darkmode = Color(r: 1, g: 1, b: 1, a: 1)
        // 色をセットする
        let ColorValueProvider = ColorValueProvider(colorScheme == .dark ? darkmode : lightmode)
        // パスを取得
        let strokePath = AnimationKeypath(keypath: "BG.Stroke 1.Color")
        let logoPath = AnimationKeypath(keypath: "logo.Group 1.Fill 1.Color")
        // 色を適用
        animationView.setValueProvider(ColorValueProvider, keypath: strokePath)
        animationView.setValueProvider(ColorValueProvider, keypath: logoPath)

        animationView.play()
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        NSLayoutConstraint.activate([
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
        return view
    }
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
    }
}
```

|ライトモード|ダークモード|
|-|-|
|![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2378a74c-3652-c652-409d-052760b7d675.gif)|![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/453ff9c4-1687-8885-8bc1-636e0e1fdcf8.gif)|

できた！

# おわり
今回作成したプロジェクトを置いとくので参考にしてください！

https://github.com/SNQ-2001/Lottie-Demo-iOS