平時進行 Native 開發的時候,為了更好的用戶體驗,我們會做一些動畫效果,而在 React Native 中也提供了相應的動畫API。
React Native 主要的動畫分為兩大類:
- LayoutAnimation 用來實現布局切換的動畫。
- Animated 更加精確的交互式的動畫。
這篇文章主要說的是 LayoutAnimation 的用法,之后會寫重點講解 Animated 的文章。
LayoutAnimation
LayoutAnimation 是在布局發生變化時觸發動畫的接口,這意味著你需要通過修改布局(比如修改了組件的style、插入新組件)來觸發動畫。一個常用的調用此API的辦法是調用 LayoutAnimation.configureNext,然后調用setState。
配置相關:
static configureNext(config: Config, onAnimationDidEnd?: Function)
計劃下一次布局要發生的動畫。
@param config 表示動畫相應的屬性:
duration 動畫持續時間,單位是毫秒。
create 配置創建新視圖時的動畫。
update 配置被更新的視圖的動畫。
@param onAnimationDidEnd 當動畫結束的時候被調用。只在iOS設備上支持。
@param onError 當動畫產生錯誤的時候被調用。只在iOS設備上支持。
static create(duration: number, type, creationProp)
用來創建 configureNext 所需的 config 參數的輔助函數。
其中 config 參數格式參考:
LayoutAnimation.configureNext({
duration: 700, //動畫持續時間
create: { //若是新布局的動畫類型
type: 'linear', //線性模式,LayoutAnimation.Types.linear 寫法亦可
property: 'opacity' //動畫屬性,除了opacity 還有一個 scaleXY 可以配置,LayoutAnimation.Properties.opacity 寫法亦可
},
update: { //若是布局更新的動畫類型
type: 'spring', //彈跳模式
springDamping: 0.4 //彈跳阻尼系數
}
});
create、update 的屬性:
duration:動畫持續時間(單位:毫秒),會覆蓋 config 中設置的 duration。
delay:延遲指定時間(單位:毫秒)。
springDamping:彈跳動畫阻尼系數(配合 spring 使用)。
initialVelocity:初始速度。
type:類型定義在LayoutAnimation.Types中:
spring:彈跳
linear:線性
easeInEaseOut:緩入緩出
easeIn:緩入
easeOut:緩出
property:類型定義在LayoutAnimation.Properties中:
opacity:透明度
scaleXY:縮放
示例:
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
Dimensions,
LayoutAnimation,
} from 'react-native';
var screenW = Dimensions.get('window').width;
var screenH = Dimensions.get('window').height;
export default class extends Component {
constructor(props) {
super(props)
this.state = {
width: 100,
height: 150,
left:20,
top:20,
}
}
_clickStartAnimation() {
LayoutAnimation.configureNext({
duration: 1000, //持續時間
create: {
type: LayoutAnimation.Types.spring,
property: 'opacity',
},
update: {
type: 'spring',
springDamping: 0.4,
}
});
this.setState({
width: this.state.width + 40,
height: this.state.height + 60,
left: this.state.left + 20,
top: this.state.top + 50,
});
}
render(){
return (
<View style={styles.mainStyle}>
<Image style={{width:this.state.width,height:this.state.height,position:'absolute',left:this.state.left, top:this.state.top}}
source={{uri:'beauty.jpg'}}>
</Image>
<TouchableOpacity style={{width:200,height:50,backgroundColor:'yellow',marginTop:40}} onPress={this._clickStartAnimation.bind(this)}>
<Text style={{width:200,height:50,textAlign:'center',lineHeight:50}}>點擊開始動畫</Text>
</TouchableOpacity>
</View>
);
}
}
效果圖:
實現拆解:
在 update 中的 type 為 spring,每次點擊按鈕,圖片都會改變寬高和位置,會有一個移動和縮放的動畫效果。
人民幣裝入紅包動畫:
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
Dimensions,
LayoutAnimation,
} from 'react-native';
var anima = {
duration: 1000, //持續時間
create: {
type: LayoutAnimation.Types.spring,
property: LayoutAnimation.Properties.scaleXY,
},
update: {
type: 'easeOut',
}
};
export default class extends Component {
constructor(props) {
super(props)
this.state = {
width: 200,
height: 100,
left:100,
top:20,
}
}
_clickStartAnimation() {
LayoutAnimation.configureNext(anima,()=>{
this.setState({
top: 20,
});
});
this.setState({
top: this.state.top + 200,
});
}
_setTimer(){
// 先開始一次動畫
this._clickStartAnimation();
// 創建定時器
this.timer = setInterval(this._clickStartAnimation.bind(this),1200);
}
render(){
return (
<View style={styles.mainStyle}>
<Image style={{width:this.state.width,height:this.state.height,position:'absolute',left:this.state.left, top:this.state.top}}
source={{uri:'100.jpg'}}>
</Image>
<View style={{
width:240,
height:120,
position:'absolute',
left:80,
top:200,
backgroundColor:'red',
}}>
<Text style={{color:'#FFD700',fontSize:90,lineHeight:104,width:240, textAlign:'center'}}>紅包</Text>
</View>
<TouchableOpacity style={{width:200,height:50,backgroundColor:'yellow',marginTop:40}} onPress={this._setTimer.bind(this)}>
<Text style={{width:200,height:50,textAlign:'center',lineHeight:50}}>點擊開始動畫</Text>
</TouchableOpacity>
</View>
);
}
}
效果圖:
實現拆解:
首先創建一個 config 變量,1秒的持續時間,type 為 easeOut,然后在點擊按鈕之后,先執行一次動畫,并同時開啟定時器,1.2秒執行一次動畫,在每次的動畫執行完成之后,讓100元回到原位,然后再次執行動畫。
魔法現金動畫:
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
Dimensions,
LayoutAnimation,
} from 'react-native';
var anima = {
duration: 1000, //持續時間
create: {
type: LayoutAnimation.Types.linear,
property: LayoutAnimation.Properties.scaleXY,
},
update: {
type: 'linear',
}
};
export default class extends Component {
constructor(props) {
super(props)
this.state = {
width: 250,
height: 125,
show:false,
}
}
_clickStartAnimation() {
LayoutAnimation.configureNext(anima,()=>{});
this.setState({
show: true,
});
}
render(){
var secondMoney = this.state.show ? (
<Image style={{width:this.state.width,height:this.state.height}}
source={{uri:'100.jpg'}}>
</Image>
) : null;
return (
<View style={styles.mainStyle}>
<Image style={{width:this.state.width,height:this.state.height}}
source={{uri:'100.jpg'}}>
</Image>
{secondMoney}
<TouchableOpacity style={{width:200,height:50,backgroundColor:'yellow',marginTop:40}} onPress={this._clickStartAnimation.bind(this)}>
<Text style={{width:200,height:50,textAlign:'center',lineHeight:50}}>魔法現金</Text>
</TouchableOpacity>
</View>
);
}
}
效果圖:
實現拆解:
首先創建一個 config 變量,1秒的持續時間,type 為 linear,property 為
scaleXY,然后在點擊按鈕之后,修改 state.show 為 true,然后根據這個屬性就會加載出一個新的100元圖片,因為是創建,不是更新,所以新的100元圖片是執行的 create 內的動畫效果,原來的100元圖片和按鈕則是執行的 update 效果。
LayoutAnimation.create
如果覺得上面的代碼太繁雜,還可以通過 LayoutAnimation.create 這個函數更簡單的創建一個config,也可以實現上面的動畫效果。
create函數接受三個參數:
- duration:動畫持續時間。
- type:create 和 update 時的動畫類型,定義在 LayoutAnimation.Types。
- creationProp:create 時的動畫屬性,定義 LayoutAnimation.Properties。
用法:
...
_clickStartAnimation() {
LayoutAnimation.configureNext(LayoutAnimation.create(1000,
LayoutAnimation.Types.linear,
LayoutAnimation.Properties.scaleXY));
this.setState({
show: true,
});
}
...
效果圖和上面一樣,參考上面即可。
LayoutAnimation.Presets
系統也為我們提供了3個默認的動畫,定義在LayoutAnimation.Presets中:
- easeInEaseOut:緩入緩出
- linear:線性
- spring:彈性
可以使用這種方式創建一些簡單的動畫效果。
用法:
...
_clickStartAnimation() {
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
this.setState({
show: true,
});
}
...
這個效果和上面類似,區別在于這個默認 Properties 是 opacity,創建過程是透明度的變化。
效果圖:
LayoutAnimation 使用總結:
- LayoutAnimation 在 React Native 中可以很好的實現動畫效果,完成可以和原生體驗相媲美,非常值得大家一試。
- 效果非常的流暢,而且動畫的過程很柔和,絲毫沒有生硬的感覺。
- 可以靈活的配置動畫參數,基本能滿足單個動畫的需求。
- 在實現紅包效果的時候,需要在動畫完成之后執行一些操作,
configureNext 第二個參數可以監聽動畫結束,從而完成這個需求,但是,這個參數只在 iOS 平臺有效,ㄟ( ▔, ▔ )ㄏ。 - 紅包動畫效果是在動畫結束之后執行了一些操作,而如果動畫的效果更為復雜,比如同時執行動畫,再順序執行,就會變的非常復雜。
Demo在這里,不麻煩的話 star 一下哈,謝謝!