首頁 > 軟體

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

2022-06-06 14:02:01

前言

我們在 頁面切換轉場動畫,英雄救場更有趣!介紹了 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自定義路徑效果動畫的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com