• 正能量網

    Flutter保姆級教程 - App如何實現復雜動畫

    作者:京東物流 沈明亮

    在App開發過程中,如果想實現動畫效果,可以粗略分為兩種方式。一種是直接用代碼編寫,像平移、旋轉等簡單的動畫效果,都可以這么干,如果稍微復雜點,就會對開發工程師的數學功底、圖形圖像學功底有很高的要求。


    另一種方式,可以讓UI同學配合,一次性出多張圖片或者直接出一張GIF圖,通過短時間內快速輪播圖片的方式來實現復雜動畫效果,這種方式真正實現起來還是有挺多問題的,比如缺少對動畫過程的控制、圖片尺寸的適配等等。那么,有沒有更好的解決方案呢?


    有的,Rive。

    簡介

    Rive是專門為簡化動畫的實現而生的,設計師可以在其官網通過拖拉拽實現各種復雜動畫效果,設計完畢后導出動畫文件,工程師可以在App里直接導入此文件,配合相應的SDK即可實現。

    其官網有詳細的開發文檔,同時也有自己的社區資源,我們可以直接從社區里下載別人設計好的動畫效果進行學習。另外特別重要的是,Rive支持跨平臺,同時支持Android、iOS、Flutter、JS、React、C++等等,本文以Flutter的實現為例介紹。

    一個完整的例子

    視頻加載中...
    1. 登陸Rive官網進行設計,并導出相應的動畫文件,Rive的動畫文件是以.riv結尾。

    本文示例是從官網的社區里找的一個個人比較喜歡的動效。

    1. 依次運行下面的命令,引入rive sdk。

    1. 將導出的.riv文件放到資源目錄下,并修改pubspec.yaml文件。

    1. 加載動畫文件并展示的核心代碼:

    核心代碼就這么多,對于代碼中的標注詳細說明下:

    • 標注1的地方,主要作用是獲取狀態機控制器,fromArtboard 方法有兩個參數,第二個參數是狀態機的名稱,這個名稱需要和UI同學協商好,一旦確定好名稱就不允許設計同學再改了,對應于設計面板界面的左下角,如下圖:

    • 標注2的地方,本例的動畫是根據“數值”的變化而變化的,findInput的入參同樣需要和UI同學協商好,一旦設計時把這個名字改了,代碼里也別忘了進行相應的修改,也在設計面板的左下角,在狀態機名稱的右邊,如下圖:

    完整的代碼如下,大家可以按步驟自己操作體驗下。

    class RiveDemo extends StatefulWidget {
      const RiveDemo({Key? key}) : super(key: key);
    
      @override
      State<RiveDemo> createState() => _RiveDemoState();
    }
    
    class _RiveDemoState extends State<RiveDemo> {
      /// 狀態機控制器
      StateMachineController? controller;
      /// 控制輸入數值
      SMIInput<double>? valueController;
      ///畫板,配合Rive widget 使用,展示動畫效果。
      Artboard? riveArtboard;
      Timer? timer;
    
      @override
      void initState() {
        super.initState();
        //加載
        rootBundle.load('asset/rives/rive_demo.riv').then((value) async {
          final file = RiveFile.import(value);
          final artboard = file.mainArtboard;
          //1
          controller = StateMachineController.fromArtboard(artboard, 'TreeMachine');
          if (controller != null) {
            setState(() {
              artboard.addController(controller!);
              //2
              valueController = controller!.findInput('input');
              valueController!.value = -4;
            });
          }
    
          riveArtboard = artboard;
        });
      }
    
      @override
      void dispose() {
        controller?.dispose();
        stopAnimation();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Rive Demo'),
          ),
          backgroundColor: Colors.white,
          body: Center(
            child: riveArtboard == null ? const CircularProgressIndicator() : Rive(artboard: riveArtboard!),
          ),
          floatingActionButton: SizedBox(
            height: 50,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                TextButton(
                  onPressed: () {
                    startAnimation();
                  },
                  child: const Text('start'),
                ),
                TextButton(
                  onPressed: () {
                    stopAnimation();
                  },
                  child: const Text('stop'),
                ),
                TextButton(
                  onPressed: () {
                    resetAnimation();
                  },
                  child: const Text('reset'),
                ),
              ],
            ),
          ),
        );
      }
    
      /// 開始動畫
      void startAnimation() {
        if (timer != null) {
          return;
        }
        timer = Timer.periodic(const Duration(milliseconds: 60), (timer) {
          valueController?.value += 0.5;
        });
      }
    
      /// 停止動畫
      void stopAnimation() {
        timer?.cancel();
        timer = null;
      }
    
      /// 重置動畫
      void resetAnimation() {
        stopAnimation();
        valueController?.value = 0;
      }
    }
    

    總結

    像本例中的動畫效果,如果用代碼來編寫,時間成本會很大很大,如果靠圖片的堆積,實現起來也很麻煩,而且由于圖片的數量增多,安裝包的體積也會增加很多。但是用rive,實現起來卻很方便,可能唯一的成本就是設計師同學的學習成本。

    Rive不僅支持本地動畫文件的加載,還可以將動畫文件放到服務器上,利用RiveAnimation.network方法進行加載。更多的使用示例可以參考:https://github.com/rive-app/rive-flutter/tree/master/example

    轉載自頭條號:京東云開發者。(侵刪)

    本站為注冊用戶提供信息存儲空間服務,非“本站編輯上傳提供”的文章/文字均是注冊用戶自主發布上傳,不代表本站觀點,版權歸原作者所有,如有侵權、虛假信息、錯誤信息或任何問題,請及時聯系我們,我們將在第一時間刪除或更正。站長郵箱(190277521@qq.com)本站是非贏利網站,本網站鄭重提醒注冊用戶:請在轉載、上載或者下載有關作品時務必尊重該作品的版權、著作權;如果您發現有您未署名的作品,請立即和我們聯系,我們會在第一時間加上您的署名或作相關處理。 轉載請注明出處:http://www.ks-zhong.com/article/a136593215252987052.html

    分享:
    掃描分享到社交APP
    發表列表
    請登錄后評論...
    游客 游客
    此處應有掌聲~
    評論列表
    x

    注冊

    已經有帳號?
     1699066960  1699066960  1699066960  1699066960  1699066960  1699066960  1699066960  1699066960  1699066960  1699066960 
    五月婷婷综合