[譯] 使用 Flutter 製做 3D 翻轉動畫

從 UI 挑戰中學習 Flutter前端

做爲個人第一篇文章的續篇,我將開始新的挑戰。這個將比前一個(微光閃爍)複雜一點。我稱之爲翻轉動畫:android

這已經足夠值得挑戰了,不是嗎?是的,咱們將製做一個看起來有些 3D 效果的動畫。ios

怎麼作呢

乍一看,有個很簡單的想法:咱們有一堆面板,每一個面板被分紅兩半,每一半能夠圍繞 X 軸旋轉並顯示下一個面板。git

如何用代碼實現呢?我把它分爲了兩個小任務:github

  • 將面板分割爲兩半
  • 圍繞 X 軸旋轉一半面板

那麼 Flutter 如何幫助咱們呢?查看 Flutter 文檔,我發現有兩個組件很是適合完成任務:ClipRectTransform後端

實現

  • 將面板分割爲兩半:

ClipRect 組件有一個 clipper 參數來定義裁剪矩形的大小和位置,可是文檔建議另外一種使用 ClipRect 的方法:將它與 Align 一塊兒使用:bash

class FlipWidget extends StatelessWidget {
  Widget child;

  FlipWidget({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        ClipRect(
            child: Align(
          alignment: Alignment.topCenter,
          heightFactor: 0.5,
          child: child,
        )),
        Padding(
          padding: EdgeInsets.only(top: 2.0),
        ),
        ClipRect(
            child: Align(
          alignment: Alignment.bottomCenter,
          heightFactor: 0.5,
          child: child,
        )),
      ],
    );
  }
}
複製代碼

嘗試一下:less

就是這樣。此外,child 可讓咱們爲所欲爲設計動畫的內容(不管如何是文本,仍是圖像)。ide

  • 圍繞 X 軸旋轉一半面板

Transform 組件有一個 transform 參數,類型是 Matrix4,用於定義所應用的變換類型。Matrix4 暴露了一個名爲 rotationX() 的工廠構造函數,看起來是咱們須要用的,讓咱們嘗試一下用在面板的上半部分:函數

@override
Widget build(BuildContext context) {
   return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Transform(
          transform: Matrix4.rotationX(pi / 4),
          alignment: Alignment.bottomCenter,
          child: ClipRect(
              child: Align(
            alignment: Alignment.topCenter,
            heightFactor: 0.5,
            child: child,
          )),
        ),
        ...
      ],
    );
  }
複製代碼

嘗試一下:

什麼!!!!它看起來像放縮效果,不是嗎?

到底怎麼回事呢?回答出這個問題是這個任務中最難的一點。我回看 Flutter 的文檔、示例代碼、文章……直到找到這篇文章。其中指出,改變 Matrix4 的第 3 行和第 2 列的值,會改變其視角,而且會給變形帶來 3D 效果:

...
Transform(
  transform: Matrix4.identity()..setEntry(3, 2, 0.006)..rotateX(pi / 4),
  alignment: Alignment.bottomCenter,
  child: ClipRect(
      child: Align(
    alignment: Alignment.topCenter,
    heightFactor: 0.5,
    child: child,
  )),
),
...
複製代碼

再試一下:

不錯。可是不如試一下神奇的數字 0.006?說實話,我不知道如何準確計算它,只是嘗試選個我感受很好的一些值。

剩下的就是爲咱們的組件添加動畫。這裏有一點點棘手。實際上,每一個面板都有兩面(正面和背面)的內容,可是在代碼中實現它並不明智,由於同一時刻只能看到一面。我假設要建立一個面板向上翻轉的動畫,那麼動畫能夠分解成連續的兩個階段(順序),第一個是向上翻轉下半部分以使動畫顯示下一個面板的下半部分,而後隱藏當前面板的下半部分,第二個是在同一方向翻轉上半部分,以顯示下一半的上半部分,同時隱藏當前的上半部分:

這個動畫實現的代碼很長,在此處插入並不太好。你能夠在本文底部的連接中找到它。這是咱們的最終效果:

真棒。咱們剛剛用 Flutter 完成了另外一個 UI 挑戰。熟能生巧。我會繼續尋找新的挑戰,使用 Flutter 解決它,並與你分享結果。感謝閱讀。

P/S:透視變換出現了個小問題(會致使變換後的圖像偏斜),我在 rotateX() 中使用一個很是小的值而不是零,能夠暫時解決這個問題。

完整代碼: gist.github.com/hnvn/f1094f…

我已將個人代碼發佈,包名爲 flip_panel

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索