Flutter(Flare) 最有趣用戶交互動畫沒有之一

2019年12月12日,FlutterFlutter Interact '19 上發佈瞭如何使用 RiveFlutter 製做動態可交互的動畫經驗分享,我看了以後,以爲很是有趣,所以,寫了3個小 demo,把它寫成文章記錄分享給你們。git

名詞理解

首先,咱們來理解幾個名詞,否則後續文章,可能看着有些暈,以下:github

  • Flare:是 Flutter 的動畫插件名稱,完整名稱是 flare_flutter 咱們要在 pubspec.yaml 文件裏引入
  • Rive:是製做 Flare 動畫的網站,它既是一個網站也是製做工具,在此網站裏有不少用戶分享 Flare 動畫供咱們下載使用、Flare API使用文檔、製做 Flare 動畫的視頻教程(你們也能夠經過學習製做本身喜歡的動畫)等

交互動畫預覽

登陸交互動畫

登陸交互動畫,包含以下6種動畫:bash

  • idle:無任何操做時的狀態(熊的身體會上下浮動和眨眼睛)
  • test:當咱們在 email 輸入框中輸入時的狀態(熊會看向輸入框,且隨着你輸入的長度旋轉頭部)
  • hands_up:當咱們在 password 輸入框中輸入時的狀態 (熊會用手蒙上眼睛)
  • hands_down:當咱們在 password 輸入框輸入完成時的狀態 (熊會放下雙手)
  • fail:當咱們登陸失敗時的狀態(熊會作出難過的表情)
  • success:當咱們登陸成功時的狀態(熊會作出高興的表情)

以上6種狀態,能夠在 Rive 網站查看具體動畫,點擊進入查看app

下面,咱們來看看案例裏實現動畫效果less

idle:無任何操做時的狀態,如圖:ide

no-shadow
idle

test:當咱們在 email 輸入框中輸入時的狀態,如圖:工具

no-shadow
test

hands_up:當咱們在 password 輸入框中輸入時的狀態,hands_down:當咱們在 password 輸入框輸入完成時的狀態,如圖:學習

no-shadow
hands_up & hands_down

fail:當咱們登陸失敗時的狀態,如圖:動畫

no-shadow
fail

success:當咱們登陸成功時的狀態,如圖:網站

no-shadow
success

Button交互動畫

button 交互動畫,如圖:

no-shadow
button

Menu交互動畫

menu 交互動畫,如圖:

no-shadow
menu

以上全部動畫,也能夠 點擊觀看視頻

代碼實現

如何用代碼實現,分爲如下2個步驟:

  • 引入插件和資源:引入相關插件 flare_fluttersmart_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…

相關文章
相關標籤/搜索