react-native動畫原生驅動
一、說明
在RN中建立動畫一般使用Animated元件,定義動畫元件,定義動畫屬性,然後使用Animated提供的幾種方法讓動畫生成。
首先,使用Animated元件生成動畫的流程圖如下:
- JS端:動畫驅動在每一幀上執行requestanimationframe方法,更新value,驅動不斷的使用新的value計算動畫視圖。
- JS端:計算內插補點,并且傳遞給綁定的view
- JS端:使用setNativeProps來更新View
- JS到原生橋接
- 原生端:View更新
是以可以看到,大多數工作都在JS端,如果JS端被阻塞,動畫将會跳幀,并且每幀都需要JS傳遞到原生端去更新。
而使用RN提供給動畫的原生驅動方式,則可以将上面所有步驟都移交至native端,當Animated元件産生動畫節點圖之後,在動畫開始時,可以進行序列化,并傳遞到native直接執行,這樣就省去了向JS端callback的過程,而原生端隻關心在UI線程的每一幀,并直接更新。
基于此,使用原生驅動的動畫流程将變為:
1. 原生端:原生動畫驅動使用CADisplayLink或者android.view.Choreographer去執行每一幀,計算并更新動畫視圖得到的新值。
2. 原生端:內插補點計算并被傳遞給綁定的原生view
3. 原生端:UIView或者android.view更新
如此,沒有更多的JS線程,沒有更多的橋接,也就意味着更快的動畫效果。
二、在APP裡使用:
在Animated動畫設定中,添加useNativeDriver字段,并設為true,注意,如果使用了useNativeDriver字段來做原生驅動,那麼做原生驅動屬性的動畫都要使用原生驅動,否則會報錯。
原生驅動也可以與Animated.event方式一同作用,
例如:
Animated.timing(this.state.animatedValue, {
toValue: ,
duration: ,
useNativeDriver: true, // <-- Add this
}).start();
<ScrollView
scrollEventThrottle={}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }]
)}
>
{content}
</ScrollView>
注意事項:
不是所有的東西都可以使用原生驅動,最主要的限制就是,你隻能使用非布局的屬性,比如transform或者opacity可以,而flexbox和位置屬性不行,另外對于Animated.event,該方式隻能工作于直接的事件而不是冒泡事件,這也就意味着,PanResponder不能使用但是scrollView的onScroll方法可以。
雖然原生驅動很早就有了,但是卻沒有文檔說明,主要是因為之前這個是一種實驗性質的方式,是以如果想用的話,確定RN的版本在0.40以上。