Flutter嚐鮮3——動畫處理<並行和串行>

圖片描述

本例的代碼參考這裏

並行動畫

當多個動畫定義同時指向某個組件,並使用動畫控制器啓動時,就產生了並行動畫(Parallel Animation)。例如我們可以讓一個組件:

  • 移動的同時改變大小
  • 旋轉的同時邊界顏色閃爍
  • 圓形圖片模糊的同時形狀越來越方

總之,掌握了動畫原理以後我們知道,只要能將一個動畫抽象值與一個組件的某個外觀屬性值聯繫起來,那麼就能在動畫中展現出連續平滑的外觀變化。這一點,任何平臺(Web、Android)的原理都是一致的。

例子

接前一篇的例子,我們讓一個移動的正方形在位移過程中逐漸變爲圓形。

在已有的animation基礎上,再添加一個新的animation用以控制動畫組件的邊角半徑。

class ParallelDemoState extends State<ParallelDemo> with SingleTickerProviderStateMixin {
    ...
    Tween<double> slideTween = Tween(begin: 0.0, end: 200.0);
    Tween<double> borderTween = Tween(begin: 0.0, end: 40.0);  // 添加邊角半徑變動範圍
    Animation<double> slideAnimation;
    Animation<double> borderAnimation; // 添加邊角半徑動畫定義
    
    @override
    void initState() {
        ...
        controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this);
        slideAnimation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear));
        borderAnimation = borderTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); // 定義邊角半徑動畫
    }
    
    ...
        
    @override
    Widget build(BuildContext context) {
        return Container(
            width: 200,
            alignment: Alignment.centerLeft,
            child: Container(
                margin: EdgeInsets.only(left: slideAnimation.value),
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(borderAnimation.value), // 邊角半徑的屬性上添加動畫
                    color: Colors.blue,
                ),
                width: 80,
                height: 80,
            ),
        );
    }
}

串行動畫

串行動畫(Sequential Animation)顧名思義,多個動畫像肉串一樣一個接一個的發生。但這只是從現象上觀察出的結果,實際的運行方式和並行動畫差別不大。串行動畫的關鍵之處在於,它爲每個動畫的發生設定了一個計時器,只有到特定時間點時,特定的動畫效果纔會發生。

例如設計一個3秒鐘的動畫:

  • 移動動畫從0秒開始,持續1秒
  • 旋轉動畫從1秒開始,持續1.5秒
  • 縮放動畫從2秒開始,持續0.7秒

那麼,最後的動畫效果便是:

  1. 0~1秒,動畫元素在移動
  2. 1~2秒,動畫元素在旋轉
  3. 2~2.5秒,動畫既在旋轉又在縮放
  4. 2.5~2.7秒,動畫在縮放
  5. 2.7~3秒,動畫靜止不動

例子

在串行動畫例子的基礎上,我們加上計時器Interval的處理。Interval有三個參數,前兩個參數指示了動畫的開始和結束時間。這兩個參數都是以動畫控制器的Duration時長的比例來計算的。例如:

  • Slide動畫分別爲0.0和0.5,表示動畫從0秒(2000ms 0.0)這個時間點開始,至1秒(2000ms 0.5)這個時間點結束
  • Border動畫分別爲0.5和1.0,表示動畫從1秒(2000ms 0.5)這個時間點開始,至2秒(2000ms 1.0)這個時間點結束
class SequentialDemoState extends State<ParallelDemo> with SingleTickerProviderStateMixin {
    ...
    
    @override
    void initState() {
        ...
        controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this);
        // slideAnimation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear));
        // borderAnimation = borderTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); // 定義邊角半徑動畫
        
        // 換一種寫法,加入Interval
        slideAnimation = slideTween.animate(CurveTween(curve: Interval(0.0, 0.5, curve: Curves.linear)).animate(controller));
        borderAnimation = borderTween.animate(CurveTween(curve: Interval(0.5, 1.0, curve: Curves.linear)).animate(controller));
    }
    
    ...
        
    @override
    Widget build(BuildContext context) {
        return Container(
            width: 200,
            alignment: Alignment.centerLeft,
            child: Container(
                margin: EdgeInsets.only(left: slideAnimation.value),
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(borderAnimation.value), // 邊角半徑的屬性上添加動畫
                    color: Colors.blue,
                ),
                width: 80,
                height: 80,
            ),
        );
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章