[譯] 關於 React Motion 的簡要介紹

lalaland本尊發表於2018-07-13

React 很棒,在過去的幾周裡,我用它玩得很開心,所以我決定嘗試一下React Motion。一開始 API 就讓我感到有困惑和棘手,但是最終一切開始變得有意義,不過這需要時間。遺憾的是,我在網上找不到合適的 React Motion 教程,所以我決定把這篇文章寫出來,不僅是作為一個開發者們的資源,也能給我自己作參考。

React Motion 對外暴露三個主要的元件:Motion, StaggeredMotion 和 TransitionMotion。在本教程中,我們將一起看一看 Motion 元件,之後你會發現將在這一部分花費大量時間。

由於這是一個 React Motion 教程,所以我將假設你有點熟悉 React 以及 ES2015。

我們將在使用 React Motion 重新建立 一個 Framerjs 的例子 時探索 API。你可以在這找到程式碼的最終版本 在這

[譯] 關於 React Motion 的簡要介紹

最終效果

我們首先要研究一點數學問題,但是不要擔心,我會盡可能詳細地解釋每一個步驟。你可以直接跳過這一部分到 React.start(); 部分。

準備好了嗎? 那就開始吧...

Math.start();

我們可以把藍色的大按鈕稱為——主按鈕, 從藍色按鈕上飛出的按鈕稱為——子按鈕。

[譯] 關於 React Motion 的簡要介紹

Fig. 1

子按鈕擁有兩種位置狀態, 1) 子按鈕均隱藏在主按鈕後面的位置, 2) 子按鈕在主按鈕周圍排列成一個圓圈的位置。

這裡就出現了數學問題,我們必須想出一種方法,在一個完美的圓中均勻地排列主按鈕周圍的子按鈕。你可以通過試錯法將這些值通過程式碼寫死,但認真的說,誰會這麼做呢?另外,一旦你找到正確的數學方法,只要你願意你可以擺放任意多的子按鈕,而他們都會自動排列自己。

首先讓我們瞭解幾個術語。

M_X, M_Y

[譯] 關於 React Motion 的簡要介紹

Fig. 2

M_X, M_Y 分別表示以主按鈕為中心的 X 和 Y 座標。(M_X, M_Y) 這個點將用作計算每個子按鈕的距離和方向的參考。

每個子按鈕最初都隱藏在主按鈕中心的後面,中心座標為 M_X, M_Y。

分離角、扇形角、飛出半徑

[譯] 關於 React Motion 的簡要介紹

Fig. 3

飛出半徑為子按鈕飛出後距離主按鈕的距離,其他兩個詞語的釋義看起來不言自明。

還需要注意一個地方,

扇形角 = (子按鈕數-1) * 分離角

現在,我們需要設計一個函式,該函式接收子按鈕 (0, 1, 2, 3 …) 的索引,並返回子按鈕的新位置的 x 和 y 的座標。

基準角、索引

[譯] 關於 React Motion 的簡要介紹

Fig. 4

由於通常來說三角學中的角度是從 x 軸的正方向測量的,我們將從相反的方向(右到左)開始給我們的子按鈕編號。這樣,以後我們就不必在每次需要子按鈕的最後位置時乘以負一。

當我們看到它時,請注意 (參見 Fig. 3)

基準角 = (180 — 扇形角)/2

(一定程度上)。

[譯] 關於 React Motion 的簡要介紹

Fig. 5

每個子按鈕都有它自己的角度,我稱之為角。這個角是計運算元按鈕最終位置所需的最後一條資訊。

請注意, (參見 Fig. 3, Fig. 4)

索引為 i 的子按鈕的角度 = 基準角 + ( i * 分離角)

現在,一旦我們有了每個子按鈕的角,

[譯] 關於 React Motion 的簡要介紹

Fig. 6

我們就能夠為每個子按鈕計算 增量X and 增量Y

請注意 (參見 Fig. 2),

子按鈕的最終 X 軸座標 = M_X + 增量X

子按鈕的最終 Y 軸座標 = M_Y - 增量Y

(我們從 M_Y 中減去增量X,因為不同於原點在左下角的一般座標系,瀏覽器的原點在左上角,所以為了方便移動,你可以降低他們 y 軸座標的值。)

所以,這些就是我們所需要的數學方法,現在我們有兩樣東西:每個子按鈕的初始位置 (M_X, M_Y) 和子按鈕的最終位置,剩下的魔發就交由 React 來完成吧!

React.start();

在下面的關鍵程式碼中,你將會看到發生什麼,點選主按鈕,我們將 isOpen 的狀態變數設定為 true (第85行)。一旦 isOpen 為 true,就會傳遞不同的子按鈕的樣式(第97行,第66行,第75行)。

結果:

[譯] 關於 React Motion 的簡要介紹

Fig. 7

好的,我們在此處完成了很多操作,我們在按鈕上設定子按鈕的初始位置和最終位置,現在我們需要做的就是新增 React Motion 來啟用在初始位置和最終位置之間的動畫。

React-Motion.start();

獲取 幾個引數 每個引數是可選的,但我們不關心這裡的可選引數,因為我們沒有做任何與這個引數有關的事情。

其中 一個引數是 style, style 將作為引數傳遞到回撥函式中,該函式包含內建的 interpolated values ,然後執行它的動畫。

(第8行 : 因為正在React中執行迭代,所以需要將一個 key 引數傳遞給子元件。)

就像這樣,

即使在這樣做以後,結果也不會與圖 Fig. 7 有所不同,為什麼這麼說?好吧,我們還需要最後一步,使用_spring_。

正如前面提到的, 回撥函式包含內建的值,也就是說, spring 幫助函式內建的值插入樣式值。

我們需要修改 initialChildButtonStylesfinalChildButtonStyles 並注意 topleftspring 覆蓋的值。這些是僅有的改變,現在,

[譯] 關於 React Motion 的簡要介紹

Fig. 8

spring 可選地接收第二個引數,這是一個包含兩個數字的陣列 [Stiffness, damping],預設值為[170,26],這導致了上圖 Fig. 8 中呈現的結果。

將 Stiffness 視為動畫發生的速度,這不是一個非常精確的假設,只是速度越大的值越大。Dampness 是一個晃動效果引數,不過相反的,值越小,晃動效果越明顯。

可以看看這個

[譯] 關於 React Motion 的簡要介紹

[320, 8] — Fig. 9

[譯] 關於 React Motion 的簡要介紹

[320, 17] — Fig. 10

我們離最終完成很近了,但是還沒有。如果我們在每次下一個子按鈕開始動畫前新增延遲會怎樣?為了達到最終效果,這正是我們需要做的,但這樣做並不那麼簡單,我不得不把每個運動元件以陣列的形式儲存到狀態變數中,然後一個一個地為每個子按鈕改變狀態以達到期望的效果,程式碼就像這樣

this.state = {  
    isOpen: false,  
    childButtons: []  
};
複製程式碼

然後在 componentDidMount 方法中新增 childButtons

 componentDidMount() {  
    let childButtons = [];  
     range(NUM_CHILDREN).forEach(index => {  
        childButtons.push(this.renderChildButton(index));  
    });

    this.setState({childButtons: childButtons.slice(0)});  
 }
複製程式碼

最終開啟選單功能得以實現:

[譯] 關於 React Motion 的簡要介紹

我們在這裡做了一些美學的調整,如新增圖示和一些旋轉效果,我們得到最終效果如下。

[譯] 關於 React Motion 的簡要介紹

方法已覆蓋,你可以設定任何數量的子按鈕

[譯] 關於 React Motion 的簡要介紹

NUM_CHILDREN = 1

[譯] 關於 React Motion 的簡要介紹

NUM_CHILDREN = 3

[譯] 關於 React Motion 的簡要介紹

NUM_CHILDREN = 8

相當酷對嗎? 再說一遍,你可以 在這找到相應程式碼。如果你覺得這篇文章有幫助,請點選下面的推薦按鈕。

如果有一些問題、評論、建議或僅僅是想聊個天?可以在 Twitter 上找到我 @NashVail 或者給我發電子郵件 hello@nashvail.me


你可能還會喜歡

  1. Let’s settle ‘this’ — Part One
  2. Let’s settle ‘this’ — Part Two
  3. Designing the perfect wallpaper app

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


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

相關文章