关于flutter:App复杂动画实现Rive保姆级教程-京东云技术团队

5次阅读

共计 2742 个字符,预计需要花费 7 分钟才能阅读完成。

作者:京东物流 沈亮堂

在 App 开发过程中,如果想实现动画成果,能够粗略分为两种形式。一种是间接用代码编写,像平移、旋转等简略的动画成果,都能够这么干,如果略微简单点,就会对开发工程师的数学功底、图形图像学功底有很高的要求。

另一种形式,能够让 UI 同学配合,一次性出多张图片或者间接出一张 GIF 图,通过短时间内疾速轮播图片的形式来实现简单动画成果,这种形式真正实现起来还是有挺多问题的,比方短少对动画过程的管制、图片尺寸的适配等等。那么,有没有更好的解决方案呢?

有的,Rive。

简介

Rive 是专门为简化动画的实现而生的,设计师能够在其官网通过利落拽实现各种简单动画成果,设计结束后导出动画文件,工程师能够在 App 里间接导入此文件,配合相应的 SDK 即可实现。

其官网有具体的开发文档,同时也有本人的社区资源,咱们能够间接从社区里下载他人设计好的动画成果进行学习。另外特地重要的是,Rive 反对跨平台,同时反对 Android、iOS、Flutter、JS、React、C++ 等等,本文以 Flutter 的实现为例介绍。

一个残缺的例子

  1. 登陆 Rive 官网进行设计,并导出相应的动画文件,Rive 的动画文件是以.riv 结尾。

本文示例是从官网的社区里找的一个集体比拟喜爱的动效。

  1. 顺次运行上面的命令,引入 rive sdk。
  1. 将导出的.riv 文件放到资源目录下,并批改 pubspec.yaml 文件。
  1. 加载动画文件并展现的外围代码:

外围代码就这么多,对于代码中的标注具体阐明下:

  • 标注 1 的中央,次要作用是获取状态机控制器,fromArtboard 办法有两个参数,第二个参数是状态机的名称,这个名称须要和 UI 同学协商好,一旦确定好名称就不容许设计同学再改了,对应于设计面板界面的左下角,如下图:
  • 标注 2 的中央,本例的动画是依据“数值”的变动而变动的,findInput 的入参同样须要和 UI 同学协商好,一旦设计时把这个名字改了,代码里也别忘了进行相应的批改,也在设计面板的左下角,在状态机名称的左边,如下图:

残缺的代码如下,大家能够按步骤本人操作体验下。

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

  @override
  State<RiveDemo> createState() => _RiveDemoState();
}

class _RiveDemoState extends State<RiveDemo> {
  /// 状态机控制器
  StateMachineController? controller;
  /// 管制输出数值
  SMIInput<double>? valueController;
  /// 画板,配合 Rive widget 应用,展现动画成果。Artboard? riveArtboard;
  Timer? timer;

  @override
  void initState() {super.initState();
    // 加载
    rootBundle.load('asset/rives/rive_demo.riv').then((value) async {final file = RiveFile.import(value);
      final artboard = file.mainArtboard;
      //1
      controller = StateMachineController.fromArtboard(artboard, 'TreeMachine');
      if (controller != null) {setState(() {artboard.addController(controller!);
          //2
          valueController = controller!.findInput('input');
          valueController!.value = -4;
        });
      }

      riveArtboard = artboard;
    });
  }

  @override
  void dispose() {controller?.dispose();
    stopAnimation();
    super.dispose();}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Rive Demo'),
      ),
      backgroundColor: Colors.white,
      body: Center(child: riveArtboard == null ? const CircularProgressIndicator() : Rive(artboard: riveArtboard!),
      ),
      floatingActionButton: SizedBox(
        height: 50,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            TextButton(onPressed: () {startAnimation();
              },
              child: const Text('start'),
            ),
            TextButton(onPressed: () {stopAnimation();
              },
              child: const Text('stop'),
            ),
            TextButton(onPressed: () {resetAnimation();
              },
              child: const Text('reset'),
            ),
          ],
        ),
      ),
    );
  }

  /// 开始动画
  void startAnimation() {if (timer != null) {return;}
    timer = Timer.periodic(const Duration(milliseconds: 60), (timer) {valueController?.value += 0.5;});
  }

  /// 进行动画
  void stopAnimation() {timer?.cancel();
    timer = null;
  }

  /// 重置动画
  void resetAnimation() {stopAnimation();
    valueController?.value = 0;
  }
}

总结

像本例中的动画成果,如果用代码来编写,工夫老本会很大很大,如果靠图片的沉积,实现起来也很麻烦,而且因为图片的数量增多,安装包的体积也会减少很多。然而用 rive,实现起来却很不便,可能惟一的老本就是设计师同学的学习老本。

Rive 不仅反对本地动画文件的加载,还能够将动画文件放到服务器上,利用 RiveAnimation.network 办法进行加载。更多的应用示例能够参考:
https://github.com/rive-app/rive-flutter/tree/master/example

正文完
 0