GameWith Advent Calendar 2018 16日目担当のkyamです。
今回は自分が好きなライブラリであるLottieを紹介します。
Lottieの存在を知っている人は多いと思いますが、イマイチ何に使えばいいのか分からない、どこに使えばいいのか分からないといった方向けに今回は気軽に導入できる実例を紹介しようと思います。
概要
- アニメーションライブラリ Lottie について
- Lottie導入と利用方法
- 実例紹介
Lottieについて
- AirBnB社が開発したアニメーションライブラリ
- デザイナーがAfter Effectsで作成したアニメーションを簡単に組み込める
- iOS, Android, React Nativeに対応
- Facebook社のライブラリKeyframesよりも機能が豊富
導入と利用方法
デザイナー側
- 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を見ているだけでも楽しいです