FlutterでAirbnbのアニメーションライブラリLottieを使う
はじめに
Qiitaから移動しました。
Flutter #2 Advent Calendar 2019 4日目です。
最近FlutterでLottieを使う機会があったので、その際調べたことを忘備録も兼ねて書いていこうと思います。 Flutter/Dart自体そこまで経験がある訳ではない(1年未満な)ので間違っている箇所などあると思います。見かけたら教えてくださると幸いです。
TL;DR
- Flutterのlottie用ライブラリはfluttieとflutter_lottieの2つがある
- fluttieは単純に使えるができることは多くない
- flutter_lottieは少し複雑だができることが多い
- fluttieがiOSデバイス未対応なので、現状としてはflutter_lottie一択?
Lottieとは
LottieとはAirbnbがリリースしたiOS/Android/React Native向けのアニメーションライブラリです。 After Effectで作成したアニメーションをリアルタイムでレンダリングし、静止画を使用するのと同じぐらい簡単に複雑なアニメーションを表示できるとのこと。
詳細はこちら AirbnbのアニメーションライブラリLottie(ロッティー)の使い方🎅 - @17genai | Qiita
How to use
を始める前に、monoさんによるFlutterアニメーションの解説を置いておきます。 直接関係する内容ではないですが参考になるので、未読の方は一度目を通しておくのをおすすめします。
- Flutterのお手軽にアニメーションを扱えるAnimated系Widgetをすべて紹介 - Flutter 🇯🇵 - Medium
- FlutterのTransition系アニメーションWidgetをすべて紹介 - Flutter 🇯🇵 - Medium
改めて、 Lottieは公式でFlutter用のライブラリとして以下の2つを紹介しています。
fluttie
使い方が単純でサクッと実装できますが複雑な操作が難しく、またiOSデバイスがサポート外です。
サンプルコード
あらかじめassetにJSON形式でLottieファイルを入れておき、引数にPathを渡してあげると表示されます。
import 'package:flutter/material.dart'; import 'package:fluttie/fluttie.dart'; class MyFluttie extends StatefulWidget { const MyFluttie({ @required this.path, Key key, }) : super(key: key); final String path; @override _MyFluttieState createState() => _MyFluttieState(); } class _MyFluttieState extends State<MyFluttie> { String _path; Fluttie _instance; @override Widget build(BuildContext context) { return Container( height: 100, width: 100, child: FutureBuilder( future: _setupAnimation(), builder: (BuildContext context, AsyncSnapshot<FluttieAnimationController> snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: case ConnectionState.active: case ConnectionState.waiting: return CircularProgressIndicator(); case ConnectionState.done: return GestureDetector( onTap: () { snapshot.data.start(); }, child: FluttieAnimation(snapshot.data), ); } }, ), ); } Future<FluttieAnimationController> _setupAnimation() async { _instance = Fluttie(); _path = widget.path; final int composition = await _instance.loadAnimationFromAsset(_path); final FluttieAnimationController animationController = await _instance.prepareAnimation(composition); return animationController; } }
_setupAnimation()
内でassetからFluttieAnimationController
を作成し、FluttieAnimation
クラスにFluttieAnimationController
を渡して描画します。
FluttieAnimationController.start()
でアニメーションがスタート。
他にもpause()
, unpause()
, stopAndReset()
が呼べます。
flutter_lottie
AnimationControllerを用いるため比較的複雑ですが、AnimationControllerでできることは大体できます。 ただしライブラリの更新がかなり怪しい(今年の2月末に公開されたきりほぼ更新されていない)のが難点です。
サンプルコード
fluttieと同じく、あらかじめassetにJSON形式でLottieファイルを入れておき、引数にPathを渡してあげると表示されます。
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:lottie_flutter/lottie_flutter.dart'; class MyLottieFlutter extends StatefulWidget { const MyLottieFlutter({ @required this.path, Key key, }) : super(key: key); final String path; @override _MyLottieFlutterState createState() => _MyLottieFlutterState(); } class _MyLottieFlutterState extends State<MyLottieFlutter> with SingleTickerProviderStateMixin { LottieComposition _composition; AnimationController _controller; @override void initState() { super.initState(); _loadAsset(widget.path).then((LottieComposition composition) { setState(() { _composition = composition; _controller.reset(); }); }); _controller = AnimationController( vsync: this, )..addListener(() => setState(() {})); } Future<LottieComposition> _loadAsset(String assetName) async { return await rootBundle .loadString(assetName) .then<Map<String, dynamic>>((String data) => json.decode(data)) .then((Map<String, dynamic> map) => LottieComposition.fromMap(map)); } @override Widget build(BuildContext context) { return Container( height: 100, width: 100, child: FittedBox( fit: BoxFit.contain, child: GestureDetector( onTap: () => setState(() { _controller.reset(); _controller.forward(); }), child: Lottie( composition: _composition, size: Size(100, 100), controller: _controller, ), ), ), ); } }
initState()
内でassetを読み込みAnimationController
とLottieComposition
をInstantiate、Lottie
クラスに渡して描画します。
アニメーションの再生はAnimationControlelr
のreset()
とforward()
で行っています。
AnimationController
なのでreverse()
やrepeat()
なども使え、flottieと比べてできることの幅が広いです。
まとめ
個人的な所感ですが、fluttieがiOSデバイス未対応な現時点ではflutter_lottie一択かなと感じています。 ただしfluttieの方が更新が多いので、今後のアップデートによっては用途によって使い分けができるようになりそうです。