Flutter利用Hero組件實現自定義路徑效果的動畫

前言

我們在 頁面切換轉場動畫,英雄救場更有趣!介紹瞭 Hero 動畫效果,使用 Hero 用於轉場能夠提供非常不錯的體驗。既然稱之為英雄,肯定還有其他技能,本篇我們就來探索一下 Hero 動畫的返回效果。

Hero 的定義

Hero 組件是一個 StatefulWidget,構造方法如下:

const Hero({
  Key? key,
  required this.tag,
  this.createRectTween,
  this.flightShuttleBuilder,
  this.placeholderBuilder,
  this.transitionOnUserGestures = false,
  required this.child,
})

其中 createRectTween 就是一個矩形插值,用於控制 Hero 組件的路徑。實際上,和普通動畫一樣,也是有一個時間曲線,取值范圍是0-1.0,然後createRectTween保證 Hero 組件動畫前後能夠達到矩形指定位置和大小。下面一張圖是官網的說明圖:

image.png

RectTween

RectTween 和 Tween類似,實際上就是矩陣在動畫過程中的變化。我們來看 RectTween 的定義:

class RectTween extends Tween<Rect?> {
  RectTween({ Rect? begin, Rect? end }) : super(begin: begin, end: end);

  /// 通過給定的動畫時間值構建新的插值矩形
  @override
  Rect? lerp(double t) => Rect.lerp(begin, end, t);
}

這個類很簡單,其實就是每次動畫時間點上調用 Rect.lerp 構建一個插值的矩形。Rect.lerp 方法如下:

static Rect? lerp(Rect? a, Rect? b, double t) {
    assert(t != null);
    if (b == null) {
      if (a == null) {
        return null;
      } else {
        final double k = 1.0 - t;
        return Rect.fromLTRB(a.left * k, a.top * k, a.right * k, a.bottom * k);
      }
    } else {
      if (a == null) {
        return Rect.fromLTRB(b.left * t, b.top * t, b.right * t, b.bottom * t);
      } else {
        return Rect.fromLTRB(
          _lerpDouble(a.left, b.left, t),
          _lerpDouble(a.top, b.top, t),
          _lerpDouble(a.right, b.right, t),
          _lerpDouble(a.bottom, b.bottom, t),
        );
      }
    }
  }

在矩形 a 和矩形 b 都不為空的時候,返回的就是一個通過定點定義的新的矩形。這裡的關鍵是_lerpDouble 方法,其實最終就是根據動畫時間完成頂點的移動。

double? lerpDouble(num? a, num? b, double t) {
  /// ...
  return a * (1.0 - t) + b * t;
}

也就是從矩形 a  的頂點逐步移動到矩形 b的頂點,從而完成瞭兩個矩形的動畫過渡。有瞭這個基礎我們就可以構建自定義的 RectTween 瞭。和我們的之前說過的動畫曲線(動畫曲線天天用,你能自己整一個嗎?看完這篇你就會瞭!)是類似的。

自定義RectTween

我們來一個自定義 RectTween,然後保證起始點是矩形 a,結束點是矩形 b,然後中間沿曲線變動就可以瞭。下面是我們利用曲線將時間轉換後得到的一個自定義 RectTween。其中使用曲線轉換後的transformT取值還是從0-1.0,然後使用_rectMove 方法就能實現從開始的矩形過渡到結束的矩形瞭。

class CustomRectTween extends RectTween {
  final Rect begin;
  final Rect end;

  CustomRectTween({required this.begin, required this.end})
      : super(begin: begin, end: end);

  @override
  Rect lerp(double t) {
    double transformT = Curves.easeInOutBack.transform(t);

    var rect = Rect.fromLTRB(
        _rectMove(begin.left, end.left, transformT),
        _rectMove(begin.top, end.top, transformT),
        _rectMove(end.right, end.right, transformT),
        _rectMove(begin.bottom, end.bottom, transformT));

    return rect;
  }

  double _rectMove(double begin, double end, double t) {
    return begin * (1 - t) + end * t;
  }
}

運行效果

可以看到結束的時候,有個回彈效果,那是因為使用瞭Curves.easeInOutBack 這個曲線。源碼已上傳至:動畫相關源碼。

運行效果

總結

本篇介紹瞭 Hero 動畫組件的 createRectTween 屬性實現自定義路徑效果的動畫。實際使用的時候,可以根據自己需要構建一些有趣的路徑提升用戶體驗或增加趣味性。

以上就是Flutter利用Hero組件實現自定義路徑效果的動畫的詳細內容,更多關於Flutter自定義路徑效果動畫的資料請關註WalkonNet其它相關文章!

推薦閱讀: