Flutter(Flare) 最有趣用户交互动画没有之一

Flutter Flare

2019年12月12日,FlutterFlutter Interact ‘19 上发布了如何使用 RiveFlutter 制作动态可交互的动画经验分享,我看了之后,觉得非常有趣,因此,写了3个小 demo,把它写成文章记录分享给大家。


名词理解

首先,我们来理解几个名词,不然后续文章,可能看着有些晕,如下:

  • Flare:是 Flutter 的动画插件名称,完整名称是 flare_flutter 我们要在 pubspec.yaml 文件里引入
  • Rive:是制作 Flare 动画的网站,它既是一个网站也是制作工具,在此网站里有很多用户分享 Flare 动画供我们下载使用、Flare API使用文档、制作 Flare 动画的视频教程(大家也可以通过学习制作自己喜欢的动画)等

交互动画预览

登录交互动画

登录交互动画,包含如下6种动画:

  • idle:无任何操作时的状态(熊的身体会上下浮动和眨眼睛)
  • test:当我们在 email 输入框中输入时的状态(熊会看向输入框,且随着你输入的长度旋转头部)
  • hands_up:当我们在 password 输入框中输入时的状态 (熊会用手蒙上眼睛)
  • hands_down:当我们在 password 输入框输入完成时的状态 (熊会放下双手)
  • fail:当我们登录失败时的状态(熊会做出难过的表情)
  • success:当我们登录成功时的状态(熊会做出高兴的表情)

以上6种状态,可以在 Rive 网站查看具体动画,点击进入查看

下面,我们来看看案例里实现动画效果

idle:无任何操作时的状态,如图:

no-shadow

test:当我们在 email 输入框中输入时的状态,如图:

no-shadow

hands_up:当我们在 password 输入框中输入时的状态,hands_down:当我们在 password 输入框输入完成时的状态,如图:

no-shadow

fail:当我们登录失败时的状态,如图:

no-shadow

success:当我们登录成功时的状态,如图:

no-shadow

Button交互动画

button 交互动画,如图:

no-shadow

menu 交互动画,如图:

no-shadow

以上所有动画,也可以 点击观看视频

代码实现

如何用代码实现,分为以下2个步骤:

  • 引入插件和资源:引入相关插件 flare_fluttersmart_flare
  • 编写代码:编写相关代码

引入插件和资源

引入插件和资源,如下:

1
2
3
4
5
6
7
8
9
10
11
12
dependencies:
...
flare_flutter: ^2.0.4 # flare 插件
smart_flare: any # 对 flare API进行封装的插件,使用少量的代码即可实现交互动画
...

assets:
...
- assets/Teddy.flr
- assets/button-animation.flr
- assets/slideout-menu.flr
...

编写代码

由于,登录交互动画稍复杂一些,在此就不展示实现的代码,如感兴趣,可移步GitHub查看源码

Button交互动画代码实现

button 交互动画代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import 'package:flutter/material.dart';
import 'package:smart_flare/actors/smart_flare_actor.dart';
import 'package:smart_flare/models.dart';

class FlareButtonDemo extends StatefulWidget {
@override
_FlareButtonDemoState createState() => _FlareButtonDemoState();
}

class _FlareButtonDemoState extends State<FlareButtonDemo> {
@override
Widget build(BuildContext context) {
var animationWidth = 295.0;
var animationHeight = 251.0;
var animationWidthThirds = animationWidth / 3;
var halfAnimationHeight = animationHeight / 2;

var activeAreas = [

ActiveArea(
area: Rect.fromLTWH(0, 0, animationWidthThirds, halfAnimationHeight),
debugArea: false,
guardComingFrom: ['deactivate'],
animationName: 'camera_tapped',
),

ActiveArea(
area: Rect.fromLTWH(animationWidthThirds, 0, animationWidthThirds, halfAnimationHeight),
debugArea: false,
guardComingFrom: ['deactivate'],
animationName: 'pulse_tapped'),

ActiveArea(
area: Rect.fromLTWH(animationWidthThirds * 2, 0, animationWidthThirds, halfAnimationHeight),
debugArea: false,
guardComingFrom: ['deactivate'],
animationName: 'image_tapped'),

ActiveArea(
area: Rect.fromLTWH(0, animationHeight / 2, animationWidth, animationHeight / 2),
debugArea: false,
animationsToCycle: ['activate', 'deactivate'],
onAreaTapped: () {
print('Button tapped!');
})

];

return Scaffold(
appBar: AppBar(
title: Text('Flare Button Demo'),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0x3fffeb3b),
Colors.orange,
]),
),
child: Align(
alignment: Alignment.bottomCenter,
child: SmartFlareActor(
width: animationWidth,
height: animationHeight,
filename: 'assets/button-animation.flr',
startingAnimation: 'deactivate',
activeAreas: activeAreas,
),
),
),
);
}
}

menu 交互动画代码实现,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import 'package:flutter/material.dart';
import 'package:smart_flare/smart_flare.dart';

class FlareSidebarMenuDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(MediaQuery.of(context).size.height);
return Scaffold(
body: Container(
child: Align(
alignment: Alignment.centerRight,
child: PanFlareActor(
width: MediaQuery.of(context).size.width / 2.366,
height: MediaQuery.of(context).size.height,
filename: 'assets/slideout-menu.flr',
openAnimation: 'open',
closeAnimation: 'close',
direction: ActorAdvancingDirection.RightToLeft,
threshold: 20.0,
reverseOnRelease: true,
completeOnThresholdReached: true,
activeAreas: [
RelativePanArea(
area: Rect.fromLTWH(0, .7, 1.0, .3), debugArea: false),
],
),
),
),
);
}
}

以上3个交互动画案例的源码,放在了我2年前写的一个 Flutter案例 的项目里了,此项目现已维护起来,以后会长期更新,感兴趣的小伙伴可以收藏,没事时来看看可能会有新的发现 😲

此篇文章到此结束,下篇文章计划给大家分享,Flutter 里的路由,会总结归纳所有的路由使用方法,最后来封装一个优秀的路由管理类。

本文结束感谢您的阅读

本文标题:Flutter(Flare) 最有趣用户交互动画没有之一

文章作者:李少颖(persilee)

发布时间:2020年07月04日 - 01:07

最后更新:2020年07月04日 - 01:07

原始链接:https://h.lishaoy.net/flutter-flare.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!