GSYFlutterBook/Z1.md

250 lines
18 KiB
Markdown
Raw Permalink Normal View History

2023-01-04 09:38:40 +08:00
# Flutter 工程化框架选择——搞定 Flutter 动画
> 本文为稀土掘金技术社区首发签约文章14天内禁止转载14天后未获授权禁止转载侵权必究
首先这次会写一个新的系列《Flutter 工程化框架选择》,但是系列其实并非前端的工程治理方面的内容,**这个系列只是单纯告诉你,创建一个 Flutter 工程,或者说搭建一个 Flutter 工程脚手架,应该如何选择快速适合自己的插件模块,或者说这是一个指引系列,相信会适合新手同学**。
> **为什么会想要写一个这样的系列?因为这类的问题太多了**,简单检索一个群的聊天记录,单单 `有没有` 这个关键字就可以搜索翻好几页,所以这个系列的目的,是帮大家整理 Flutter 工程里可能会需要的各种第三方模块,并对比一些技术细节,**也是方便以后回答问题我可以直接甩链接**。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image1.png)
首先作为系列第一篇文章,本篇我们先聊动画。
为什么第一篇聊它,因为近期刚好做了一些关于 Flutter 动画的调研,不久前也刚好发布过一些关于它的内容,所以素材比较多,而本篇将针对你可能会遇到的动画场景,**给你推荐各式各样的动画框架来加速开发**。
# 前言
在之前的 [Flutter 小技巧](https://juejin.cn/post/7111071430292275213) 系列里我们聊过,如果没有使用封装, Flutter 里创建动画一般需要:
- `AnimationController` 用于控制动画启动、暂停
- `TickerProvider` 用于创建 `AnimationController` 所需的 `vsync` 参数,一般最常使用 `SingleTickerProviderStateMixin`
- `Animation` 用于处理动画的 value ,例如常见的 `CurvedAnimation`
- 接收动画的对象:例如 `FadeTransition`
这种写法如下代码所示,我们一般可以称为显式动画(不要纠结名词叫法),大致特征就是:以 **`*Transition`** 命名,比如 `FadeTransition` 、`SizeTransition` 和 `RotationTransition` 等,**需要我们自己定义和操作 `AnimationController`** 。
```dart
class _AnimatedOpacityState extends State<AnimatedOpacity>
with TickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
late final Animation<double> _animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: FadeTransition(
opacity: _animation,
child: const Padding(padding: EdgeInsets.all(8), child: FlutterLogo()),
),
);
}
}
```
但是,如果都采用这种方式去使用动画,那么项目里就会存在很多的重复代码,所以 Flutter 官方默认提供了一些动画封装,也可以叫做隐式动画(不要纠结名词叫法):
> **也就是开箱即用**,常见是 **`Animated*`** 开头的 Widget例如 `AnimatedPositioned` 、`AnimatedContainer` 、 `AnimatedPadding` 、`AnimatedOpacity` 等控件,它们最大的特点就是内部已经完全封装好逻辑,你只需要配置对应参数就可以触发动画。
如下代码所示,你只需要改变 `_width``_height` 就可以触发动画效果,动画中间过程的数据会通过 `Curves` 变化的 “插值” 来得到。
```dart
body: Center(
child: AnimatedContainer(
width: _width,
height: _height,
decoration: BoxDecoration(
color: _color,
borderRadius: _borderRadius,
),
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
),
),
```
虽然隐式动画挺方便,但真正的项目里可能很多情况还是不满我们的需求,往往业务逻辑会需要更灵活或者更细致的封装,那么这就要聊到本篇后面的内容。
# 基础动画
说到基础动画的部分,主要就是在隐式动画的基础上进一步的封装,可以通过简单配置快速实现一些更精致的动画效果。
## animations
[animations](https://github.com/flutter/packages/tree/main/packages/animations) 是官方封装的动画库,主要卖点在于 Material 风格的动画过渡,所以**这个库的核心重点是路由过渡动画或者页面切换动画**,例如下图就是 Demo 里利用库里自带的 `OpenContainer` 实现页面跳转的 Material 过渡 效果。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image2.gif)
另外也可以使用 `PageTransitionSwitcher` 实现一些非路由的页面切换动画,可以理解为是一个变异版本的 `AnimatedSwitcher` ,或者是 `Stack` 版动画 `PageView` ,不过支持自定义进入和退出动画,还可以支持自定义布局,一般默认使用默认 `defaultLayoutBuilder` 的话,就是使用 `Stack` 作为布局。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image3.gif)
官方 Demo 里也会使用 `PageTransitionSwitcher` 来做步进页面跳转的效果,**所以 [animations](https://github.com/flutter/packages/tree/main/packages/animations) 的核心动画能力主要是在于页面过渡方面**。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image4.gif)
> 总的来说,这个库是官方维护,值得信赖。
## simple_animations
[simple_animations](https://github.com/felixblaschke/simple_animations) 如同它的名字所示,它主要是简化了自定义动画的过程,正如前面所示,在 Flutter 里使用动画,我们一般需要定义 `AnimationController` 、`Animatable` 和 `Animation` 等对象来配置动画效果。
而 simple_animations 提供了 `AnimationMixin` 对象,如下代码所示,你只需要通过 `with` 关键字就可以简化接入动画的代码。
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image5.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image6.png) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image7.gif) |
| ------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------- |
同时 simple_animations 也提供了各种 Builder 来简化,例如使用 `MirrorAnimationBuilder` 就可以实现一个循环反复的动画效果。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image8.png)
**所以 simple_animations 针对显式动画进行了优化封装,在更方便的情况下做到能更灵活控制动画效果**,如下图所示,在 [gsy_fluter_demo](https://github.com/CarGuo/gsy_flutter_demo/tree/master/lib/widget/particle) 里就利用了 simple_animations 来实现一些动画效果:
- `MirrorAnimation``MovieTween ` 实现渐变的背景
- `LoopAnimation``MovieTween` 实现了粒子动画
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image9.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image10.gif) |
| ---------------------------------------- | ------------------------------------------ |
> 不过这个库有个小问题,就是它最近几次大版本,每个版本总是会有一些 break change ,但是可能就是改改名字,换换参数位置,如果你一段时间没关注,再升级可能会有些成本。
## animate_do
**[animate_do](https://github.com/Klerith/animate_do_package) 是一个轻量级动画包,它比 simple_animations “更懒”,代码也相对简单很多,内部提供了丰富的动画封装 Widget 可直接使用**。
> 你可以理解为更丰富的隐式动画。
animate_do 就是通过 `AnimatedBuilder ` 配合 `Transform` 、`Opacity` 进行了封装,然后开发者可以通过 `FlipInX` 、`FadeInDown` 、`ElasticIn` 等对象直接实现动画效果。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image11.png)
既然 animate_do 十分简单,那为什么会推荐它呢?因为它真的很实用。
**首先简单代表着好维护,作者不玩了我们自己也能接**,其次 animate_do 提供了相当丰富的封装,这对于懒人来说它真的很实用,特别是对于一些 “相对复杂” 的动画效果上如下图3可以节省很多时间特别是在 `Tween``CurvedAnimation`的封装上。
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image12.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image13.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image14.gif) |
| --------------------------------------- | ----------------------------------------- | --------------------------------------- |
> 目前有一段时候没更新,但是问题不大~ 同类型的库还有 [spring](https://github.com/KaushickSArgekar/spring) ,可以作为替代项目,也实现了类似的封装。
# UI 动画
介绍完基础动画效果,接下来推荐一些常用的动画框架,因为经常有人问到`有没有xxx` 的实现可以直接拿来使用,秉承着有做好的就不自己动手原则,下面这些 UI 动画框架,也许在你开发过程中就会需要用到。
> UI 动画部分就不介绍实现了,主要就看功能符不符合你需求。
## 数字动画
首先是数字动画,常见的有 [flutter-animated-counter](https://github.com/h65wang/flutter-animated-counter) ,本身它就提供了丰富的 API 和动画效果,类似的第三方库还有 [odometer](https://github.com/KirsApps/odometer) 和 [animated_digit ](https://github.com/mingsnx/animated_digit) 等,具体可以自己按需选择。
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image15.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image16.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image17.gif) |
| ------------------------------------------- | ------------------------------------------- | ----------------------------------------- |
## 跑马灯
既然聊到文字动画,就不得不说跑马灯,如下表格所示是 Flutter 里常用到的文字跑马灯的第三方 package ,其中 [marquee_widget](https://github.com/yousifk/marquee_widget) 提供的接口相对更佳丰富。
| [marquee_widget](https://github.com/yousifk/marquee_widget) | [text_scroll](https://github.com/yurii-khi/text_scroll) | [marquee_text](https://pub.dev/packages/marquee_text) |
| ----------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------- |
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image18.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image19.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image20.gif) |
## 加载动画
加载动画是最常见的 UI 动画,如果你没有设计师,如果你不知道 loading 动画用什么好,那你可以考虑下面几个 package这三个 loading 库都是纯代码实现,提供了丰富的样式选择。
| [flutter_spinkit](https://github.com/jogboms/flutter_spinkit) | [loading_animation_widget](https://github.com/watery-desert/loading_animation_widget) | [loading_indicator](https://github.com/TinoGuo/loading_indicator) |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image21.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image22.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image23.gif) |
> 纯代码实现有什么好处?当样式需要做一些简单调整时,作为开发者可以通过代码快速修改,这是我喜欢纯代码实现动画的原因。
## 指引动画
指引动画也是常见的需求之一,基本实现都会通过 `Overlay` 来完成,不同的可能就是动画效果和定位方式的差异,具体也可以按照自己的需要选择。
| [feature_discovery](https://github.com/ayalma/feature_discovery) | [flutter_showcaseview](https://github.com/simformsolutions/flutter_showcaseview) | [flutter_intro](https://pub.dev/packages/flutter_intro) | [BubbleShowcase](https://github.com/Skyost/BubbleShowcase) |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | ---------------------------------------------------------- |
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image24.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image25.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image26.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image27.gif) |
## 列表动画
列表动画也是常见的 UI 动画能力之一,基本上 Flutter 上最常见用都的第三方列表动画库就是下面表格里这三个,坑还是有的,但是“又不是不能用”。
| [flutter_staggered_animations](https://github.com/mobiten/flutter_staggered_animations) | [animation_list](https://github.com/turlvo/flutter_animation_list) | [transformable_list_view](https://github.com/TBR-Group-software/transformable_list_view) |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image28.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image29.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image30.gif) |
## 3D 立体动画
这个类目可能关注的人反而不是很多,但是恰好是我近期比较关注的动画实现,这里主要推荐两个利用矩阵变换绘制 3D 视觉效果的第三方库,它们不同在于:
- zwidget 能力相对比较弱,直接使用的是 `Transform` 的能力
- zflutter 来源于前端 zdog 项目,是直接对 `Canvas``path` 进行矩阵变换
| [zflutter](https://github.com/jamesblasco/zflutter) | [zwidget](https://github.com/apalala-dev/zwidget) |
| --------------------------------------------------- | ------------------------------------------------------ |
| ![](http://img.cdn.guoshuyu.cn/20220806_N11/image30.gif) | ![](http://img.cdn.guoshuyu.cn/20220920_Z1/image31.gif) |
在不久前我也写过一篇文章 [《Flutter 实现 “真” 3D 动画效果》](https://juejin.cn/post/7129239231473385503),内容主要分析了 zflutter 的实现逻辑和如何使用 zflutter ,利用纯代码渲染 3D 效果的动画。
> 当然,上门两个 3D 动画,它们在使用上相对会比较复杂,如果需要更高级的动画效果,建议看下面的推荐。
# 高级动画支持
介绍完面向程序员的动画支持之后,最后我们来介绍两个面向设计师的动画支持库,同时也是更好支持复杂动画实现的库。
## Lottie
[Lottie](https://github.com/xvrh/lottie-flutter) 相信大家不会陌生,[airbnb ](https://github.com/airbnb) 最优秀的动画开源库,设计师可以通过 AE 插件导出设计好的动画效果,然后利用平台的 `Canvas` 等能力渲染出 AE 上的动画效果。
![](http://img.cdn.guoshuyu.cn/20220920_Z1/image32.gif)
**使用 Lottie 的好处在于,设计师可以更自由的去尝试更炫酷的动画**,而程序员只需要关心如何控制动画(时长,循环,方向,帧率等),同时因为动画大部分时候都是矢量数据,所以 Lottie 文件相对不大。
> 在早期的时候,由于 Lottie 本身只支持原生平台,所以 Flutter 上都是通过外界纹理或者 `PlatformView ` 等形式接入,这样的后果就是导致各种性能和兼容问题,好在现在 [lottie-flutter](https://github.com/xvrh/lottie-flutter) 已经支持 Dart `Canvas` 的原生 API 。
当然, Lottie 本身的问题也很明显,那就是你的交互设计师要会 AE ,很遗憾的是,我接触的大部分设计师都不会 AE ,而且会 AE 还不够,还需要会 [Bodymovin](https://github.com/airbnb/lottie-web) 插件相关的兼容,熟悉什么属性可以用,整体开发环境也比较重。
## Rive
对于 **[rive](https://link.juejin.cn/?target=https%3A%2F%2Frive.app)** 可能大家会感觉比较陌生,而做过 Flutter 开发的可能对 rive 会有所耳闻,因为 rive 在此之前叫 flare ,是 2dimensions 公司的开源动画产品,在发布之初由于和 Flutter 团队有深入合作,所以在初期一直是 Flutter 官方推荐的动画框架。
| ![](http://img.cdn.guoshuyu.cn/20220731_N10/image3.gif) | ![](http://img.cdn.guoshuyu.cn/20220731_N10/image4.png) |
| ------------------------------------------------------- | ------------------------------------------------------- |
**[rive](https://link.juejin.cn/?target=https%3A%2F%2Frive.app)** 同样是一个面向设计师的动画框架,只不过他是在 **Web Editor** 里进行 UI 编排和动画绘制,所以他在开发环境上相对会轻量化。
| ![](http://img.cdn.guoshuyu.cn/20220731_N10/image18.gif) | ![img](http://img.cdn.guoshuyu.cn/20220731_N10/image9.gif) | ![img](http://img.cdn.guoshuyu.cn/20220731_N10/image10.gif) |
| ------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------- |
同时 rive 同样是通过导出矢量的动画数据文件(也可以包含一些静态资源),然后利用平台的 `Canvas` 来实现动画效果,所以它的占用提及也不会很大。
另外 rive 现在也是全平台支持, **Android、 iOS、Web、Desktop、Flutter 、React、Vue、C++** 等都在支持范围之内。
> 如果想深入了解 rive ,也可以看我之前的 [《给掘金 Logo 快速添加动画效果》](https://juejin.cn/post/7126661045564735519) 其实对于程序员来说rive 同时很好上手。
![](http://img.cdn.guoshuyu.cn/20220731_N10/image1.gif)
> 目前 rive 的问题是,第二代 rive 和第一代 flare 存在断档不兼容,而且基本可以忽略迁移的可能,同时没有本地化免费开发 IDE 有时候也是一种麻烦。
好了,关于 Flutter 动画相关的内容推荐就到这里,如果你还有什么关于 Flutter 工程或者框架的疑问,欢迎留言评论,也许又可以多一期的素材~