2019年12月12日,Flutter 在 Flutter Interact '19 上釋出瞭如何使用 Rive 和 Flutter 製作動態可互動的動畫經驗分享,我看了之後,覺得非常有趣,因此,寫了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:無任何操作時的狀態,如圖:
test:當我們在 email 輸入框中輸入時的狀態,如圖:
hands_up:當我們在 password 輸入框中輸入時的狀態,hands_down:當我們在 password 輸入框輸入完成時的狀態,如圖:
fail:當我們登入失敗時的狀態,如圖:
success:當我們登入成功時的狀態,如圖:
Button互動動畫
button 互動動畫,如圖:
Menu互動動畫
menu 互動動畫,如圖:
以上所有動畫,也可以 點選觀看視訊
程式碼實現
如何用程式碼實現,分為以下2個步驟:
- 引入外掛和資源:引入相關外掛
flare_flutter
、smart_flare
- 編寫程式碼:編寫相關程式碼
引入外掛和資源
引入外掛和資源,如下:
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 互動動畫程式碼實現如下:
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互動動畫程式碼實現
menu 互動動畫程式碼實現,如下:
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 裡的路由,會總結歸納所有的路由使用方法,最後來封裝一個優秀的路由管理類。
最後附上部落格和專案地址,如下:
部落格地址:h.lishaoy.net/flutter-fla…
專案地址:github.com/persilee/fl…