[RN] requestAnimationFrame幀動(dòng)畫

前言

動(dòng)畫是移動(dòng)應(yīng)用中的一個(gè)相當(dāng)重要的組成部分,一個(gè)用戶體驗(yàn)良好的應(yīng)用通常都具有流暢、有意義的動(dòng)畫。類似原生平臺(tái),React Native也為我們提供了豐富的動(dòng)畫API:requestAnimationFrame、LayoutAnimation、Animated。

requestAnimationFrame:幀動(dòng)畫,是最容易實(shí)現(xiàn)的一種動(dòng)畫,通過不斷改變組件的state值,從而在視覺上產(chǎn)生一種動(dòng)畫的效果,類似于gif動(dòng)畫的方式。

LayoutAnimation:布局動(dòng)畫,當(dāng)布局發(fā)生改變時(shí)的動(dòng)畫模塊,允許在全局范圍內(nèi)創(chuàng)建和更新動(dòng)畫,這些動(dòng)畫會(huì)在下一次渲染或布局周期運(yùn)行,實(shí)現(xiàn)單個(gè)動(dòng)畫非常簡(jiǎn)潔,體驗(yàn)和性能良好。

Animated:用于創(chuàng)建更精細(xì)的交互控制的動(dòng)畫,可進(jìn)行多個(gè)動(dòng)畫的組合動(dòng)畫,具備極高的性能,是功能最強(qiáng)大的動(dòng)畫API。

本節(jié)我們先介紹requestAnimationFrame。

requestAnimationFrame幀動(dòng)畫的實(shí)現(xiàn)

requestAnimationFrame實(shí)現(xiàn)幀動(dòng)畫的原理非常粗暴簡(jiǎn)潔,即通過修改state值來不斷得改變視圖上的樣式,從而在視覺上產(chǎn)生一種動(dòng)畫的效果。

import React, { Component } from'react';

import {

AppRegistry,

StyleSheet,

Text,

View,

TouchableOpacity,

Platform,

} from'react-native';

exportdefaultclassFrameAnimationDemo extends Component {

constructor(props){

super(props);

this.state = {

width:200,

height:20,

};

}

_onPress() {

//每按一次增加近30寬高

varcount =0;

while(++count<30){

requestAnimationFrame(()=>{

this.setState({

width:this.state.width +1,

height:this.state.height +1

});

})

}

}

render() {

return(

<Viewstyle={styles.container}>

<Viewstyle={[styles.content,{width:this.state.width,height:this.state.height}]}>

<Textstyle={[{textAlign:'center'}]}>Hello World!</Text>

</View>

<TouchableOpacitystyle={styles.content}onPress={this._onPress.bind(this)}>

<Viewstyle={styles.button}>

<Textstyle={styles.buttonText}>Press me!</Text>

</View>

</TouchableOpacity>

</View>

);

}

}

const styles = StyleSheet.create({

container: {

marginTop:25,

flex: 1,

},

content: {

backgroundColor: 'rgba(200, 230, 255, 0.8)',

marginBottom:10,

justifyContent:"center",

alignSelf:"center",

},

button: Platform.select({

ios: {},

android: {

elevation: 4,

// Material design blue from https://material.google.com/style/color.html#color-color-palette

backgroundColor: '#2196F3',

borderRadius: 2,

width:100,

height:30,

},

justifyContent:"center",

alignSelf:"center",

}),

buttonText: {

alignSelf:"center",

}

});

從效果上看動(dòng)畫有種一頓一頓的感覺。這是由于通過修改state值,導(dǎo)致頻繁地銷毀、重繪視圖,內(nèi)存開銷大,從而使得動(dòng)畫卡頓明顯。另外對(duì)于幀動(dòng)畫而言,如果幀數(shù)較少,動(dòng)畫的效果會(huì)比較生硬,幀數(shù)過多又會(huì)引發(fā)性能問題。

優(yōu)化

如果幀動(dòng)畫的方式更符合當(dāng)前對(duì)動(dòng)畫的控制方式,我們可以對(duì)上述方法做一點(diǎn)優(yōu)化,在requestAnimationFrame中采用setNativeProps直接修改組件的屬性并觸發(fā)局部刷新,不會(huì)導(dǎo)致重繪組件,因此在性能上優(yōu)于直接修改state的方法。

修改_onPress方法,將對(duì)this.setState的直接修改改為對(duì)”Hello World”按鈕的屬性修改this.refs.view1.setNativeProps。

_onPress() {

varcount =0;

while(++count<30){

requestAnimationFrame(()=>{

this.refs.view1.setNativeProps({

style: {

width:this.state.width++,

height:this.state.height++

}

});

});

}

}

this.refs.view1指向的是”Hello World”文字的父視圖。

<View ref="view1"style={[styles.content, {width:this.state.width, height:this.state.height}]}>

<Textstyle={[{textAlign:'center'}]}>Hello World!</Text>

</View>

通過對(duì)比可以看出流暢順滑多了。

每個(gè)動(dòng)畫API都有其適應(yīng)和不適應(yīng)的場(chǎng)景,如果要實(shí)現(xiàn)“彈性動(dòng)畫”,“緩入緩出”等效果,使用requestAnimationFrame還是比較難的,需要輔助各種函數(shù)。下一節(jié)將介紹另一種動(dòng)畫API——LayoutAnimation。

GitHub地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容