11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GameWithAdvent Calendar 2018

Day 16

Lottieを使ってアプリのUXを高める

Posted at

GameWith Advent Calendar 2018 16日目担当のkyamです。
今回は自分が好きなライブラリであるLottieを紹介します。
Lottieの存在を知っている人は多いと思いますが、イマイチ何に使えばいいのか分からない、どこに使えばいいのか分からないといった方向けに今回は気軽に導入できる実例を紹介しようと思います。

概要

  • アニメーションライブラリ Lottie について
  • Lottie導入と利用方法
  • 実例紹介

Lottieについて

  • AirBnB社が開発したアニメーションライブラリ
  • デザイナーがAfter Effectsで作成したアニメーションを簡単に組み込める
  • iOS, Android, React Nativeに対応
  • Facebook社のライブラリKeyframesよりも機能が豊富

Examples2.gif

導入と利用方法

デザイナー側

  • After EffectsのプラグインBodymovinを用いてアニメーションのjsonファイルを出力
  • そのファイルをエンジニア側に渡す

エンジニア側

  • Cocoapods or Carthageでライブラリのインストール
  • lottie-iosのライブラリを用いてjsonファイルを読み込んで表示

デザイナーから画像ファイルなどを貰う必要はありません。
jsonファイルのダウンロードにも対応しているので、外部にファイルを置いてA/Bテストなども容易にできます。

実例紹介

UIRefreshControlをlottie製に

final class RefreshControl: UIRefreshControl {
    private lazy var loadingView: LOTAnimationView = {
        let loadingView = LOTAnimationView(name: "loading")
        loadingView.contentMode = .scaleAspectFill
        self.addSubview(loadingView)
        return loadingView
    }()
    override init(frame: CGRect) {
        super.init(frame: .zero)
        setup()
        makeConstraints()
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    private func setup() {
        backgroundColor = .clear
        tintColor = .clear
    }
    private func makeConstraints() {
        loadingView.snp.makeConstraints({ (make) in
            make.center.equalToSuperview()
            make.size.equalTo(150)
        })
    }
}

extension RefreshControl {
    func startLoading() {
        loadingView.play()
    }
    func stopLoading() {
        loadingView.stop()
        endRefreshing()
    }
}

UIActivityIndicatorの代わりにLOTAnimationViewを使う

private let spinnerTag = 1000

extension UIViewController {
    func startActivityIndicator() {
        run_main(sync: false) {
            let loadingView = LOTAnimationView(name: "loading")
            loadingView.contentMode = .scaleAspectFill
            loadingView.tag = spinnerTag
            self.view.addSubview(loadingView)
            loadingView.play()
            loadingView.snp.makeConstraints({ (make) in
                make.size.equalTo(150)
                make.center.equalToSuperview()
            })
        }
    }
    func stopActivityIndicator() {
        run_main(sync: false) {
            if let loadingView = self.view.subviews.filter({$0.tag == spinnerTag}).first as? LOTAnimationView {
                loadingView.stop()
                loadingView.removeFromSuperview()
            }
        }
    }
}

※ AutoLayoutの部分はSnapKitのライブラリを用いた書き方をしています。
run_main はよくあるDispathQueue.mainを扱いやすくしたものです。

func run_main(sync: Bool, delay: Double = 0, block: @escaping () -> Void) {
    if sync {
        if Thread.isMainThread {
            block()
        } else {
            DispatchQueue.main.sync(execute: block)
        }
    } else {
        if delay == 0 {
            DispatchQueue.main.async(execute: block)
        } else {
            let dispatchTime: DispatchTime = DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
            DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: block)
        }
    }
}

まとめ

  • 導入や実装が容易のためエンジニアサイドの実装コストが激減します。
  • デザイナーさんが作ったアニメーションが再現できる

エンジニアのレベル感にもよりますが、デザイナーさんが作ったアニメーションをフルスクラッチで再現するのは物によっては結構大変です。
ですがlottie-iosを使えばデザイナーさんの作業コストはかかりますがデザイナーさんにとっても希望のアニメーションをエンジニア側がそのまま利用できるのでwinwinかもしれません。

まだ全てのAfterEffectsの機能に対応しているわけではないため、必ずしも理想のアニメーションが作れるわけではないですが是非一度デザイナーさんと一緒に触って見てください!

lottiefilesを見ているだけでも楽しいです:cat2:

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?