【Flutter】Lottie 1つのファイルから複数アニメーションを実装する
今回やること
複数の Lottie アニメーションを実装する際に、アニメーションごとに複数のファイルに分けるのではなく、
1 つのファイルに複数のアニメーションを集約し、実装時に個別アニメーションを抽出する。
つまりやりたいのは、6.0 秒のアニメーションの中で 4.0~6.0 の間をループするなど、部分的に切り出してアニメーションを実装することです。
個別アニメーションをインタラクティブに活用した例
Lottie の構成
このように 1 つのアニメーションに対し、部分的にそれぞれの個別アニメーションを作成します。
作成した個別アニメーション: Hover, Send, Done, Failed, Load
1 つのファイルを連続再生すると下のようになります。これを部分的に切り取って使用します。
専用のコントローラーを作成する
特定の部分をループさせたり、特定の部分のアニメーションのみを実行したいので、
専用のコントローラーを作ると便利です。AnimationController を継承します。
アニメーションの値は 0.0~1.0 で管理されるので、開始時間などは startSecond/duration(アニメーションの総時間) のように表します。
ループするアニメーション、フォワードするアニメーションを実装する。
個別のアニメーションの開始の秒数と終了の秒数を引数として取ります。
class LottieAnimationController extends AnimationController {
LottieAnimationController({
required super.vsync,
super.duration,
});
void dispose() {
super.dispose();
_removeCurrentListener();
}
AnimationStatusListener? _listener;
void pointLoop(
double startSecond,
double endSecond, {
bool reverse = false,
}) {
_removeCurrentListener();
if (reverse) {
repeat(
min: startSecond / duration!.inSeconds,
max: endSecond / duration!.inSeconds,
reverse: true,
period: Duration(seconds: (endSecond - startSecond).toInt()));
} else {
value = startSecond / duration!.inSeconds;
animateTo(endSecond / duration!.inSeconds);
_listener = (status) {
if (status == AnimationStatus.completed) {
value = startSecond / duration!.inSeconds;
animateTo(endSecond / duration!.inSeconds);
}
};
}
addStatusListener(_listener!);
}
Future<void> pointForward(double startSecond, double endSecond) async {
_removeCurrentListener();
value = startSecond / duration!.inSeconds;
return animateTo(endSecond / duration!.inSeconds);
}
void _removeCurrentListener() {
if (_listener != null) {
removeStatusListener(_listener!);
_listener = null;
}
}
}
実装側
開始秒数と終了秒数を指定して部分的にアニメーションさせる。
late LottieAnimationController _lottieController;
void initState() {
super.initState();
_lottieController = LottieAnimationController(
duration!.inSeconds: 6.0,// 今回のアニメーションファイルの総時間
vsync: this,
);
}
/// hover アニメーションを実行する (0.0~1.0)
_lottieController.pointLoop(0.0, 1.0);
/// send アニメーションを実行する (1.0~1.6)
_lottieController.pointForward(1.0, 1.6);
/// build内
Lottie.asset(
'assets/lottie/send.json',
controller: _lottieController,
onLoaded: (composition) {
/// ロード時にアニメーションの総時間を取得する
_lottieController.duration = composition.duration;
},
),
hover
send
終わりに
今回は Lottie を Flutter で応用的に使用してみました。
個別のアニメーションごとにファイルを分けて管理するのも良いですが、
ファイルを 1 つにまとめると asset も煩雑にならずに管理が楽かなと思います。
また、Lottie は json ファイルですので、データを加工しやすいのも良いですね。
デモページ ↓ 下記ページからデモとコードを確認できます。
Discussion