React-Native 動畫優化

前言

動畫對於客戶端來講是很是重要的一部分,直接影響到應用的用戶體驗。前端對於動畫優化一般使用CSS3樣式來實現動畫,以利用GPU加速特性。而React-Native因爲渲染模式的不一樣,沒法使用CSS樣式的方式優化。前端

React-Native的實現

React-Native在動畫方面有兩個主要方式,一個是Animated,一個是LayoutAnimation。react

Animated

Animated動畫庫的原理是由JavaScript來進行動畫的計算,而後在每幀設置對應組件的style來實現動畫過程(requestAnimationFrame)。
這個動畫庫的特色是很是靈活,由於全部的控制都是經過JavaScript實現的,動畫補幀都是在JavaScript端完成,能夠實現各類複雜動畫效果,包括跟手動畫等。android

可是成也JavaScript敗也JavaScript,JavaScript是單線程的,動畫的特色是要保證流暢就要保證每秒60的幀率,也就是說若是在16ms內處理不完,勢必要掉幀。而在實際業務中,播放動畫的同時通常都會執行一些任務處理邏輯。好比數據拉取、數據計算,典型狀況一般會伴有Loading動畫,切換頁面過場時伴隨新頁面數據加載等。在複雜場景下,因爲業務邏輯的加入,動畫處理的幀率就很難保證,用咱們QA的話說就是卡的像個Web。。。typescript

優勢:npm

  • 可實現複雜動畫
  • 很是靈活
  • 能夠兼容Web

缺點:react-native

  • 性能問題,掉幀、卡頓

LayoutAnimation

React-Native自帶還有一種動畫的實現方式,就是LayoutAnimation。這種方案是直接在Native實現一些動畫效果,而後由JavaScript進行設置調用,因爲整個動畫過程交由Native處理,使得性能得以保證。不過LayoutAnimation的實現思路有點問題,他只是預置了幾個動畫效果,而且只能配置在create/update/delete的時候,須要自定義的動畫、跟手動畫等都無法實現。異步

優勢:ide

  • 性能良好

缺點:post

  • 動畫效果簡單,可適用範圍較窄

嘗試解決

給他特權

針對Animated的優化思路就是解決動畫播放時JavaScript任務量的問題,保證動畫循環達到60幀。一個典型的解決方案就是暫時中止全部同步任務的處理,等到動畫執行完成以後再同步或異步的執行任務處理。好比在切頁轉場前暫停耗時操做(延遲Redux的dispatch過程等),轉場動畫結束後再進行同步或異步處理,把大的同步任務用setTimeout等方式拆成多個異步過程處理。性能

這種方案能夠必定程度上解決動畫卡頓的問題,可是有幾個缺點:

  • 任務老是要執行的,延遲處理會致使整個處理過程變長,響應用戶操做速度變慢,影響用戶體驗。
  • 治標不治本,複雜動畫該卡還得卡。。。

優勢:

  • 改動較少,成本低,萬一之後facebook改進了呢?好比在獨立線程進行動畫渲染計算?(須要解決數據同步問題,WebWorker也是個坑)
  • 能夠實現跟手動畫,控制好JavaScript的任務量,效果還能夠

因此此方案適用 動畫相對簡單、後續任務不復雜 的場景

原生優化

要從根本上解決問題,就須要讓動畫過程脫離JavaScript。因此就要開發原生組件來實現動畫過程,這樣能夠充分利用機器性能,可使用GPU進行動畫渲染。還須要考慮靈活性,若是隻能實現固定的效果那麼使用場景就大打折扣。

然而,咱們並不須要從頭設計,OC、Android、WPF,都有優秀的動畫API,咱們還等什麼?抄吧。

(So,歡迎使用 react-native-animation 支持iOS、Android,目前驗證可行、能用、不完善、待重構,歡迎PR~)

舉個小栗子:

<Animation.AnimationView
    data={[{
        type: 'Alpha',
        from: 0,
        to: 1,
        duration: 500,
    }]} autoplay={true}>
        other views...
</Animation.AnimationView>

*Now support: 'Translate' | 'Rotate' | 'Scale' | 'Alpha'

Props:

export interface PropsDefine {
    data: AnimationModel[]
    style?: React.ViewStyle
    autoplay?: boolean
    autoclear?: boolean
    onStart?: (view: AnimationView) => void
    onEnd?: (view: AnimationView) => void
}

數據模型:

export interface AnimationModel {
    name?: string
    type: 'Translate' | 'Rotate' | 'Scale' | 'Alpha'
    from?: number
    to?: number
    from2?: number
    to2?: number
    duration: number
    startOffset?: number
    interpolator?: 'Linear'
    interpolatorData?: number
    repeat?: number
}

效果演示:
iOS微粉App(android版兼容開發中),業務邏輯全React-Native實現。贊踩動畫、彈幕動畫、切頁動畫、回覆/評論彈層動畫已應用優化。

雖然這種方案能夠解決可預測的動畫得卡頓問題,缺點也很明顯:

  • 動畫的過程是預設好的,因此沒法實現跟手動畫

優勢:

  • 動畫過程交由Native處理,性能Max,JavaScript任務處理不影響動畫效果,可並行

因此此方案適用 可預測的動畫 的場景

結語

雖然React-Native標榜的就是性能更好,但也只是跟Web對比而言,跟Native比仍是有很多差距的,跟Xamarin等跨平臺方案對比性能也差距不小,因此在開發時仍是要關注下性能問題,性能調優仍是要花很多精力去解決的。

微粉iOS:

相關文章
相關標籤/搜索