[譯] React Native 中使用轉場動畫!

talisk發表於2018-08-07

這篇文章有近 15k 的瀏覽量。對某些人來說,這可能沒什麼,但對我來說是一個很大的動力。這正是我決定構建 Pineapple — Financial Manager 的原因。僅僅 20 天,我已經完成了 iOS 版Android 版以及網頁版,花費 300 美金,並寫了幾篇關於它的文章。我無法用言語表達我多麼享受這段時間。你也應該試試!

最近我試圖為下一個動畫挑戰尋找靈感。我們開始吧 —— 由 Ivan Parfenov 建立。我很好奇我是否能夠用 React Native 來做這個過渡效果。你可以在我的 expo 帳戶中檢視結果!為什麼我們還需要這樣的動畫?來讀讀 Pablo Stanley 寫的絕佳的 UI 動畫技巧

[譯] React Native 中使用轉場動畫!

Ivan Parfenov 設計的 PLΛTES

我們可以看到有幾個動畫。工具欄(顯示/隱藏),底欄(顯示/隱藏),移動所選專案,隱藏所有其他專案,顯示詳細資訊專案甚至更多。

[譯] React Native 中使用轉場動畫!

動畫時間線。

過渡動畫的難點在於同步所有這些動畫。因為我們需要等到所有動畫都完成,我們無法真正移除列表頁面並顯示詳細資訊頁面。此外,我對整潔的程式碼有所追求。程式碼要易於維護,如果您曾嘗試為專案實現動畫,則程式碼通常會變得混亂。到處都是輔助變數,各種計算等。這正是我想介紹 react-native-motion 的原因。

[譯] React Native 中使用轉場動畫!

對 react-native-motion 的一個小想法

你能看到工具欄標題的動畫嗎?你只需稍微移動標題並將不透明度設定為 0 或 1。這很簡單!但正因為如此,你需要編寫這樣的程式碼,甚至在你真正開始為該元件編寫 UI 之前。

class TranslateYAndOpacity extends PureComponent {
  constructor(props) {
    // ...
    this.state = {
      opacityValue: new Animated.Value(opacityMin),
      translateYValue: new Animated.Value(translateYMin),
    };
    // ...
  }
  componentDidMount() {
    // ...
    this.show(this.props);
    // ...
  }
  componentWillReceiveProps(nextProps) {
    if (!this.props.isHidden && nextProps.isHidden) {
      this.hide(nextProps);
    }
    if (this.props.isHidden && !nextProps.isHidden) {
      this.show(nextProps);
    }
  }
  show(props) {
    // ...
    Animated.parallel([
      Animated.timing(opacityValue, { /* ... */ }),
      Animated.timing(translateYValue, { /*  ... */ }),
    ]).start();
  }
  hide(props) {
    // ...
    Animated.parallel([
      Animated.timing(opacityValue, { /* ... */ }),
      Animated.timing(translateYValue, { /*  ... */ }),
    ]).start();
  }
  render() {
    const { opacityValue, translateYValue } = this.state;

    const animatedStyle = {
      opacity: opacityValue,
      transform: [{ translateY: translateYValue }],
    };

    return (
      <Animated.View style={animatedStyle}>{this.props.children}</Animated.View>
    );
  }
}
複製程式碼

現在讓我們來看看如果用 react-native-motion 實現這個動畫,要怎麼做。我知道動畫經常是非常具體的。我知道 React Native 提供了非常強大的動畫 API。無論如何,擁有一個帶有基本動畫的庫會很棒。

import { TranslateYAndOpacity } from 'react-native-motion';

class ToolbarTitle extends PureComponent {
  render() {
    return (
      <TranslateYAndOpacity duration={250}>
        <View>
          // ...
        </View>
      </TranslateYAndOpacity>
    );
  }
}
複製程式碼

共享的元素

這一挑戰的最大問題是移動選定的列表項。列表頁面和詳細資訊頁面之間共享的專案。當元素實際上沒有絕對定位時,如何將專案從 FlatList 移動到 Detail 的頁面頂部?使用 react-native-motion 非常容易。

// List items page with source of SharedElement
import { SharedElement } from 'react-native-motion';

class ListPage extends Component {
  render() {
    return (
      <SharedElement id="source">
        <View>{listItemNode}</View>
      </SharedElement>
    );
  }
}
複製程式碼

我們在 ListPage 上指定了 SharedElement 的 source 元素。現在我們需要對 DetailPage 上的目標元素執行幾乎相同的操作,來知道我們想要移動共享元素的位置。

// Detail page with a destination shared element
import { SharedElement } from 'react-native-motion';

class DetailPage extends Component {
  render() {
    return (
      <SharedElement sourceId="source">
        <View>{listItemNode}</View>
      </SharedElement>
    );
  }
}
複製程式碼

黑科技在哪裡?

我們如何將相對定位的元素從一個頁面移動到另一個頁面?實際上我們做不到。SharedElement 的工作方式如下:

  • 獲取源 element 的位置
  • 獲取目標 element 的位置(顯然,沒有這一步,動畫不能被初始化)
  • 建立共享的 element(黑科技!)
  • 在螢幕上方渲染一個新圖層
  • 渲染 element 元素,將覆蓋源 element(在源 element 的位置上)
  • 開始移動到目標 element 位置
  • 一旦移動到目標 element 位置後,刪除克隆 element

[譯] React Native 中使用轉場動畫!

你可以想象在同一時刻同一個 React Node 有 3 個 element。這是因為在移動動畫期間,DetailPage 會覆蓋列表頁面。這就是為什麼我們可以看到所有 3 個元素。但是我們想要創造一種我們實際移動了原始 element 的幻覺。

[譯] React Native 中使用轉場動畫!

SharedElement 的時間線。

您可以看到 A 點和 B 點。這是移動正在執行的時間段。您還可以看到 SharedElement 觸發一些有用的事件。在這種情況下,我們使用 WillStart 和 DidFinish 事件。在啟動移動目標 element 時,將源 element 和目標 element 的不透明度設定為 0,並在動畫完成後將目標 element 的不透明度設定為 1。

你覺得怎麼樣?

社群這裡一直不斷在維護和更新:react-native-motion。這絕不是這個庫的最終和穩定版本。但是一個好的開始 :) 我很想聽聽你怎麼想!

我一直在尋找新的挑戰和機會。如果您需要幫助,請告訴我,我很樂意討論它。

LinkedIn || Github || Twitter || Facebook || 500px

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


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

相關文章