[译]Flutter lottie库lottie

2,084 阅读3分钟

「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」。

本文翻译自pub: lottie | Flutter Package (flutter-io.cn)

译时版本: lottie 1.2.1


用于 Flutter 的 Lottie

Lottie 是用于 Android 和 iOS 的移动端库,它解析 Adobe After Effects 动画,使用 Bodymovin 导出为 json ,在移动端进行原生渲染。

该库使用纯 Dart 编写,是 Lottie-android 库的一个非官方版本。

它可以在 Android、iOS、 macOS、 linux、 windows 和 web 上使用。

用法

简单动画

本示例用最简单的方式展示了如何显示 Lottie 动画。 Lottie 组件会加载 json 文件,然后无限循环地运行动画。

import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView(
          children: [
            // 从资源加载 Lottie 文件
            Lottie.asset('assets/LottieLogo1.json'),

            // 从远程 URL 加载 Lottie 文件
            Lottie.network(
                'https://rawgit.flutter-io.cn/xvrh/lottie-flutter/master/example/assets/Mobilo/A.json'),

            // 从 zip 文件加载动画和图像。
            Lottie.asset('assets/lottiefiles/angel.zip'),
          ],
        ),
      ),
    );
  }
}

指定自定义 AnimationController (动画控制器)

本示例展示了通过自定义的 AnimationController 对动画进行完全控制。

使用自定义的 AnimationController ,会有丰富的 API 以多种方式播放动画:随时开始和终止动画、前进或后退、在两个指定点之间循环 。。。

import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(vsync: this);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView(
          children: [
            Lottie.asset(
              'assets/LottieLogo1.json',
              controller: _controller,
              onLoaded: (composition) {
                // 配置 AnimationController
                // 指定了 Lottie 文件的时长,然后开始播放动画。
                _controller
                  ..duration = composition.duration
                  ..forward();
              },
            ),
          ],
        ),
      ),
    );
  }
}

该文件 是一个更广泛的示例。

控制组件大小

在控制大小方面,Lottie 组件接收和 Image 同样的参数,和 Image 也有相同的行为。

Lottie.asset(
  'assets/LottieLogo1.json',
  width: 200,
  height: 200,
  fit: BoxFit.fill,
)

width 和 height 是可选的,且反馈到父组件应用的大小或 lottie 动画的固有大小。

自定义加载

Lottie 组件有几个方便的构造方法( Lottie.asset 、 Lottie.network 、 Lottie.memory)来自动加载、解析和缓存 json 文件。

有时你可能更希望完全控制文件的加载。可使用 LottieComposition.fromByteData 从字节列表解析文件。

本示例展示了如何从 json 文件加载和解析 Lottie 作品。

class MyWidget extends StatefulWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late final Future<LottieComposition> _composition;

  @override
  void initState() {
    super.initState();

    _composition = _loadComposition();
  }

  Future<LottieComposition> _loadComposition() async {
    var assetData = await rootBundle.load('assets/LottieLogo1.json');
    return await LottieComposition.fromByteData(assetData);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<LottieComposition>(
      future: _composition,
      builder: (context, snapshot) {
        var composition = snapshot.data;
        if (composition != null) {
          return Lottie(composition: composition);
        } else {
          return const Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}

自定义绘制

本示例偏底层,展示了如何在自定义的 Canvas 中以指定位置和大小的帧绘制 LottieComposition 。

class CustomDrawer extends StatelessWidget {
  final LottieComposition composition;

  const CustomDrawer(this.composition, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _Painter(composition),
      size: const Size(400, 400),
    );
  }
}

class _Painter extends CustomPainter {
  final LottieDrawable drawable;

  _Painter(LottieComposition composition)
      : drawable = LottieDrawable(composition);

  @override
  void paint(Canvas canvas, Size size) {
    var frameCount = 40;
    var columns = 10;
    for (var i = 0; i < frameCount; i++) {
      var destRect = Offset(i % columns * 50.0, i ~/ 10 * 80.0) & (size / 5);
      drawable
        ..setProgress(i / frameCount)
        ..draw(canvas, destRect);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

在运行时更改属性

本示例展示了如何在运行时更改动画的某些属性。这里我们改变了一些层的文本、颜色、透明度和位置。对于每一个 ValueDelegate ,我们可以提供静态的 value (值)或者 callback (回调)来计算每一帧的值。

class _Animation extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Lottie.asset(
      'assets/Tests/Shapes.json',
      delegates: LottieDelegates(
        text: (initialText) => '**$initialText**',
        values: [
          ValueDelegate.color(
            const ['Shape Layer 1', 'Rectangle', 'Fill 1'],
            value: Colors.red,
          ),
          ValueDelegate.opacity(
            const ['Shape Layer 1', 'Rectangle'],
            callback: (frameInfo) => (frameInfo.overallProgress * 100).round(),
          ),
          ValueDelegate.position(
            const ['Shape Layer 1', 'Rectangle', '**'],
            relative: const Offset(100, 200),
          ),
        ],
      ),
    );
  }
}

局限

该包支持 Lottie Android 相同的特性集

Flutter Web 

使用该命令运行: flutter run -d chrome --web-renderer canvaskit

这里可以预览: xvrh.github.io/lottie-flut…

更多示例

查看 example 文件夹,有更多的代码示例,展示了多方面的可能性。