flutter動畫入門

對于前端來說,我感覺最大的魅力就是在于動畫效果了;最初入坑前端就是想做出炫酷的動畫,其實可以學習AE什么的,當時不懂,就入了前端程序員的坑。當然用代碼實現(xiàn)出炫酷的動畫效果,更會讓自己充滿成就感。

封面.gif

1. 動畫簡介

在一段時間內(nèi),快速地多次改變UI外觀,由于人眼會產(chǎn)生視覺殘留,所以最后會看到連續(xù)的動畫。對于人眼來說,動畫幀率超過16FPS,就比較流暢了,超過32FPS就會非常的細膩平滑,而超過32FPS,人眼基本上就感受不到差別了。由于動畫的每一幀都是要改變UI輸出,所以在一個時間段內(nèi)連續(xù)的改變UI輸出是比較耗資源的,對設(shè)備的軟硬件系統(tǒng)要求都較高,所以在UI系統(tǒng)中,動畫的平均幀率是重要的性能指標,而在Flutter中,理想情況下是可以實現(xiàn)60FPS的,這和原生應用能達到的幀率是基本是持平的?!?《flutter實戰(zhàn).動畫簡介》

2. flutter動畫

在web前端,我們實現(xiàn)動畫可以通過css過渡元素,定義css關(guān)鍵幀,js等定義動畫函數(shù)等方式去實現(xiàn),那么flutter如何去實現(xiàn)動畫效果呢?如果是想簡單的實現(xiàn)動畫,可以選擇flutter內(nèi)置的一些動畫Widget,flutter已經(jīng)封裝好了:AnimatedPadding,AnimatedPositionedAnimatedOpacity,AnimatedAlign,AnimatedContainerAnimatedDefaultTextStyle,這些拿來即用,但是這些不能隨心控制;想要自己自定義實現(xiàn)動畫的話那就需要以下的幾個步驟:

  • 創(chuàng)建一個動畫控制器AnimationController
  • 添加一個描述動畫的過程Curve,返回的是一個Animation
  • 添加tween,控制動畫的執(zhí)行范圍,需要執(zhí)行animate方法,返回Animation
    AnimationController: 創(chuàng)建動畫控制器,默認動畫執(zhí)行范圍是[0,1],如果需要改變的話,需要用到tween

3. 開始制作簡單的動畫

動畫效果:一個正方形,先變大,然后變顏色,然后再變小,還原顏色
前提準備,新建好項目,新建class AnimationDemo

class AnimationDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return AnimationDemoState();
  }
}

class AnimationDemostate extends State<AnimationDemo> with SingleTickerProviderStateMixin {
  // SingleTickerProviderStateMixin 性能有關(guān),需要執(zhí)行Ticker
  // 動畫控制器需要傳這個參數(shù),效果是在頁面不可見的區(qū)域,動畫不會執(zhí)行,避免消耗資源。
}
3.1 定義動畫和控制器變量
class AnimationDemostate extends State<AnimationDemo> with SingleTickerProviderStateMixin {
  // SingleTickerProviderStateMixin 性能有關(guān),需要執(zhí)行Ticker
  // 動畫控制器需要傳這個參數(shù),效果是在頁面不可見的區(qū)域,動畫不會執(zhí)行,避免消耗資源。
Animation animation;
AnimationController _animationController;
}
3.2 初始化動畫變量

我們先嘗試讓紅色的正方形在3秒內(nèi)從10的寬高變道300的寬高,以下代碼中做了以下幾步

  1. 先創(chuàng)建了一個動畫控制器,duration動畫的持續(xù)時間,vsync這個就是當前的State
  2. 創(chuàng)建了一個動畫函數(shù)CurvedAnimation它的是一個Animation
  3. 創(chuàng)建Tween,begin:10.0,end: 300.0,這個就是在3秒之內(nèi)會生成10~300的值
    new Tween它是繼承Animatable<T>,而不是跟CurvedAnimation一樣繼承Animation;那我們創(chuàng)建的Animatable如何與Animation形成映射呢?答案是執(zhí)行animate方法把Animation傳進去,就形成了新的Animation,我們就可以在Widget中愉快使用了它了。
  4. 執(zhí)行動畫 _animationController.forward();
class AnimationDemostate extends State<AnimationDemo> with SingleTickerProviderStateMixin{
  ···
   @override
  void initState() {
    // TODO: implement initState
    _animationController = new AnimationController(
      duration: Duration(seconds: 3),
      vsync: this,
    );
    animation = new CurvedAnimation(
      parent: _animationController,
      curve: Curves.ease
    );
    // Tween begin,end 就是大小變化的區(qū)間
    animationSize = new Tween(begin: 10.0, end: 300.0).animate(animation)
      ..addListener((){
        setState(() {
          
        });
      });
    
    _animationController.forward();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        ···
          new Container(
            width: animationSize.value,
            height: animationSize.value,
            decoration: BoxDecoration(
              color: Colors.red,
            ),
          )
        ···
    )
  }
  ···
}

經(jīng)過上面步驟之后我們來看下效果:


紅色正方形變大.gif

皆大歡喜,我們已經(jīng)成功了第一步!能有動畫的效果了,我們繼續(xù)深入后續(xù)的步驟

3.3 讓紅色正方形變大的過程中變成其他顏色

這種相當于是關(guān)鍵幀的意思,就是先變大,在變大的過程中某個時間開始變顏色;在web中我們知道css中有@keyframe可是設(shè)置關(guān)鍵幀,來進行交織動畫,flutter中我們?nèi)绾螌崿F(xiàn)呢?
在3.2步驟中我們創(chuàng)建過一個動畫曲線CurvedAnimation,curve傳的是flutter內(nèi)置的動畫函數(shù)Curves.ease,在vscode中打出Curves后編輯器會有提示所有的內(nèi)置的函數(shù);我們要打關(guān)鍵幀的話,關(guān)鍵在于此curve,這里需要用到Interval(start, end),這個Interval通過start和end我們就能知道了,它表示的是一段時間間隔,可以傳入curve參數(shù)。
了解上面的內(nèi)容之后,我們思路應該清爽了,那繼續(xù)深入

3.3.1 使正方形變大的過程中由紅色變成藍色
class xxx extends xxx with xxx {
  // 定義變量
  Animation animationColor;
  // 初始化變量
  void initState() {
     // TODO: implement initState
    _animationController = new AnimationController(
      duration: Duration(seconds: 3),
      vsync: this,
    );
    animation = new CurvedAnimation(
      parent: _animationController,
      curve: new Interval(0, 0.5) // 這里執(zhí)行間隔 是3秒中0~50%的時間執(zhí)行正方形變大,默認動畫
    );
    animationSize = new Tween(begin: 10.0, end: 300.0).animate(animation)
      ..addListener((){
        setState(() {
          
        });
      });
    animation = new CurvedAnimation(
      parent: _animationController,
      curve: new Interval(0.5, 1.0, curve: Curves.easeIn) // 50%~100%執(zhí)行變顏色,并且動畫是easeIn
    );
    animationColor = new ColorTween(begin: Colors.white, end: Colors.blue).animate(animation)
      ..addListener((){
        setState(() {
          
        });
      });
  }
}

通過上面步驟之后
我們來看看最終的的效果:


紅色正方形動畫.gif

最后想實現(xiàn)循環(huán)往復的效果

需要在動畫監(jiān)聽狀態(tài)中去改變動畫的方向就可以了
方法如下:

animation.addStatusListener((status){
      if (status == AnimationStatus.completed) {
          _animationController.reverse();
        } else if (status == AnimationStatus.dismissed) {
          _animationController.forward();
        }
      });

來看看效果:


最終效果.gif

總結(jié)

這邊主要是對flutter動畫的一個簡單的入門,按照上面步驟一步步的去實現(xiàn)flutter的動畫,應該就會對flutter動畫有了一定的了解了,具體深入的了解可以看官方文檔和其他資料的書籍,如果文中有講述不到位的地方,或者有錯誤的地方,也請大佬們多多指教,康桑密達!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容