GSYFlutterBook/Z1.md

250 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 工程或者框架的疑问,欢迎留言评论,也许又可以多一期的素材~