實(shí)現(xiàn)動(dòng)畫的幾種方式:
- requestAnimationFrame
- setNativeProps
- LayoutAnimation
- Animated
本篇文章我們會(huì)介紹前三種方式漓拾,以及它們的區(qū)別骇两。下一篇文章會(huì)介紹高級(jí)API—Animated的用法。
requestAnimationFrame
如果不使用任何動(dòng)畫API配阵,我會(huì)想到一種簡單粗暴的方式來實(shí)現(xiàn)動(dòng)畫效果—通過修改state
不斷改變視圖的樣式棋傍。
我們來個(gè)簡單的示例:
class Demo9 extends Component {
constructor(props) {
super(props);
this.state = {
width: 100,
height: 100
};
}
startAnimation() {
var count = 0;
while (++count < 50) {
requestAnimationFrame(() = >{
this.setState({
width: this.state.width + 1,
height: this.state.height + 1
});
});
}
}
render() {
return (
<View style = {styles.container}>
<Image source = { require('./icon.jpg') }
style={{width: this.state.width, height: this.state.height}}/>
<TouchableOpacity style={styles.instructions} onPress={()=>this.startAnimation()}>
<Text style={{alignSelf: 'center', color: '#FFFFFF'}}>Press me!</Text>
</TouchableOpacity>
</View>
);
}
}
效果圖如下:
這個(gè)方式實(shí)現(xiàn)的動(dòng)畫有幾個(gè)問題:
1瘫拣、實(shí)現(xiàn)方式是通過不斷銷毀麸拄、創(chuàng)建視圖來完成,一方面如果你的視圖的數(shù)據(jù)是動(dòng)態(tài)獲取的,那么就需要以合適的方式恢復(fù)數(shù)據(jù)失球;另外一方面实苞,這種方式必然造成性能和內(nèi)存開銷的問題烈疚。
2爷肝、如果需要刷新的View的層級(jí)比較深,那么這種方式會(huì)帶來嚴(yán)重的性能問題金赦。
3夹抗、requestAnimationFrame
畢竟是web
上css
的用法纵竖,在手機(jī)上靡砌,動(dòng)畫的效果比較生硬通殃,如果需要‘彈性動(dòng)畫’,‘淡入淡出’等效果恨诱,則是比較難以實(shí)現(xiàn)的(需要輔助各種函數(shù))照宝。
setNativeProps
如果執(zhí)意使用修改state的方式句葵,覺得這種方式更符合當(dāng)前需求對(duì)動(dòng)畫的控制,那么則應(yīng)當(dāng)使用原生組件的setNativeProps
方法來做對(duì)應(yīng)實(shí)現(xiàn)把将,它會(huì)直接修改組件底層特性忆矛,不會(huì)重繪組件催训,因此性能也遠(yuǎn)勝動(dòng)態(tài)修改組件內(nèi)聯(lián)style的方法。
我們稍微修改下startAnimation
方法:
startAnimation() {
var count = 0;
while (++count < 50) {
requestAnimationFrame(() = >{
this.refs.image.setNativeProps({
style: {
width: this.state.width++,
height: this.state.height++
}
});
});
}
}
其中this.refs.image
指向的是Image視圖亚兄,效果圖如下(比上一種方式流暢多了~):
優(yōu)點(diǎn):
setNativeProps
直接修改組件底層特性,不會(huì)重繪組件礼旅,因此性能也遠(yuǎn)勝動(dòng)態(tài)修改組件內(nèi)聯(lián)style的方法各淀。缺點(diǎn):
1碎浇、
setNativeProps
屬于原生視圖的方法,如果我們使用一個(gè)動(dòng)畫泉唁,單純只是為了跟蹤它的值弄跌,那么這么方法有點(diǎn)不合時(shí)宜。2跟磨、還是和上面一種方式一樣,如果需要實(shí)現(xiàn)‘彈性動(dòng)畫’攒盈,‘淡入淡出’等效果抵拘,則還是比較麻煩的。
重點(diǎn)型豁,本篇文章的主角要登場了(此處有掌聲~)
LayoutAnimation
當(dāng)布局變化時(shí)僵蛛,自動(dòng)將視圖運(yùn)動(dòng)到它們新的位置上尚蝌。
一個(gè)常用的調(diào)用此API的辦法是調(diào)用LayoutAnimation.configureNext(config)
,然后調(diào)用setState
充尉。
建議大家閱讀的時(shí)候打開
LayoutAnimation
源碼飘言,路徑為:
xxx/node_modules/react-native/Libraries/LayoutAnimation/LayoutAnimation.js
驼侠,其中‘xxx’為當(dāng)前項(xiàng)目文件夾姿鸿。
一個(gè)標(biāo)準(zhǔn)的config
格式如下:(create
、update
和delete
泪电,分別表示視圖創(chuàng)建
般妙、更新
和刪除
時(shí)候的動(dòng)畫)
示例:
{
duration: 700, //持續(xù)時(shí)間
create: { // 視圖創(chuàng)建
type: LayoutAnimation.Types.linear,
property: LayoutAnimation.Properties.scaleXY // opacity纪铺、scaleXY
},
update: { // 視圖更新
type: LayoutAnimation.Types.spring,
springDamping: 0.4
},
}
其中create
相速、update
和delete
的Anim
格式如下:
delay:延遲指定時(shí)間(單位:毫秒)
springDamping:彈跳動(dòng)畫阻尼系數(shù)(配合spring
使用)
initialVelocity:初始速度
type:類型定義在LayoutAnimation.Types
中:
- spring:彈跳
- linear:線性
- easeInEaseOut:緩入緩出
- easeIn:緩入
- easeOut:緩出
property:類型定義在LayoutAnimation.Properties
中:
- opacity:透明度
- scaleXY:縮放
讓我們來看一段示例代碼,同樣是修改startAnimation
方法:
startAnimation() {
LayoutAnimation.configureNext({
duration: 700, //持續(xù)時(shí)間
create: { // 視圖創(chuàng)建
type: LayoutAnimation.Types.spring,
property: LayoutAnimation.Properties.scaleXY,// opacity鲜锚、scaleXY
},
update: { // 視圖更新
type: LayoutAnimation.Types.spring,
},
});
this.setState({width: this.state.width + 10, height: this.state.height + 10});
}
效果圖如下:
觀察下這個(gè)動(dòng)畫:
視圖創(chuàng)建的時(shí)候是縮放動(dòng)畫突诬,點(diǎn)擊‘Press Me!’,圖片也會(huì)有個(gè)縮放動(dòng)畫芜繁。
我們還可以通過LayoutAnimation.create
這個(gè)函數(shù)更簡單的創(chuàng)建一個(gè)config
旺隙,同樣可以實(shí)現(xiàn)和上圖一樣的效果。
startAnimation() {
LayoutAnimation.configureNext(LayoutAnimation.create(700,
LayoutAnimation.Types.spring,
LayoutAnimation.Properties.scaleXY));
this.setState({width: this.state.width + 10, height: this.state.height + 10});
}
create
函數(shù)接受三個(gè)參數(shù):
- duration:動(dòng)畫持續(xù)時(shí)間骏令。
- type:
create
和update
時(shí)的動(dòng)畫類型蔬捷,定義在*LayoutAnimation.Types
。 - creationProp:
create
時(shí)的動(dòng)畫屬性榔袋,定義在LayoutAnimation.Properties
周拐。
附create
的源碼:
效果圖和上圖一樣,這里不在貼出來了凰兑。
實(shí)際上妥粟,系統(tǒng)已經(jīng)為我們提供了3個(gè)默認(rèn)的動(dòng)畫,定義在LayoutAnimation.Presets
中:
- easeInEaseOut:緩入緩出
- linear:線性
- spring:彈性
一個(gè)簡單的示例:
startAnimation() {
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
this.setState({width: this.state.width + 10, height: this.state.height + 10});
}
具體參數(shù)配置吏够,請(qǐng)查看Presets
源碼:
我們來分析下LayoutAnimation的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
1勾给、效果非常的流暢,而且動(dòng)畫的過程很柔和锅知,絲毫沒有生硬的感覺播急。
2、可以靈活的配置動(dòng)畫參數(shù)售睹,基本能滿足單個(gè)動(dòng)畫的需求旅择。
缺點(diǎn):
1、如果要實(shí)現(xiàn)‘組合順序’動(dòng)畫侣姆,比如先縮小50%生真、再向左平移100像素沉噩,那么就比較麻煩了,需要監(jiān)聽上一個(gè)動(dòng)畫的結(jié)束事件柱蟀,再進(jìn)行下一個(gè)川蒙。那么問題來了,configureNext
第二個(gè)參數(shù)是可以監(jiān)聽動(dòng)畫結(jié)束的长已,但是只在IOS平臺(tái)有效畜眨!
2、如果動(dòng)畫的效果更為復(fù)雜术瓮,比如同時(shí)執(zhí)行動(dòng)畫康聂,再順序執(zhí)行,對(duì)于編程來講胞四,需要做的事情很多恬汁,復(fù)雜度也大大提升。
那么如何定制更靈活豐富的動(dòng)畫效果呢辜伟,這就需要使用到高級(jí)動(dòng)畫API Animated氓侧。下一篇文章我們會(huì)介紹高級(jí)動(dòng)畫API—Animated的使用,感興趣的朋友請(qǐng)繼續(xù)閱讀[React Native]動(dòng)畫-Animated导狡。
本文的源碼地址:Demo9