一.介紹
動畫類型:
spring:基礎(chǔ)的單次彈跳物理模型
timing:從時間范圍映射到漸變的值
decay:以一個初始速度開始并且逐漸減慢停止
創(chuàng)建動畫的參數(shù):
value:AnimatedValue | AnimatedValueXY(X軸或Y軸 | X軸和Y軸)
config:SpringAnimationConfig | TimingAnimationConfig | DecayAnimationConfig(動畫的參數(shù)配置)
組件類型:
Animated.Text
Animated.Image
Animated.View:可以用來包裹任意視圖
Animated.createAnimatedComponent():其它組件(較少用,用Animated.View包裹可以達(dá)到同樣的效果)
import React, {Component} from 'react';
import {
StyleSheet,
View,
Animated,
Image,
Easing
} from 'react-native';
import {Button} from "react-native-elements";
/**
* @mark 文件內(nèi)變量
*/
//文件內(nèi)變量結(jié)束
export default class AnimatedDeomo extends React.Component {
/***
* default props value
* @mark propTypes 默認(rèn)屬性值
*/
static defaultProps = {}
/***
* props types for helper text
* @mark propTypes 屬性類型
*/
static propTypes = {}
/**
* @mark state
*/
state = {
fadeOutOpacity: new Animated.Value(0),
trans: new Animated.ValueXY({
x: 0,
y: 0
}),
rotation: new Animated.Value(0),
scale: new Animated.Value(1),
left: new Animated.Value(0),
}
/**
* @mark constructor
*/
constructor(props) {
super(props);
}
/**
* @mark 組件聲明周期區(qū)域
*/
/**
* @mark 第一次加載 只運行一次
*/
componentDidMount() {
}
//聲明周期代碼結(jié)束
/**
* @mark 自定義代碼區(qū)
*/
/**
* @mark 淡入淡出
*/
OpacityHandle(){
this.startOpacity();
}
startOpacity() {
Animated.timing(this.state.fadeOutOpacity, {
toValue: 1,
duration: 2000,
easing: Easing.linear,// 線性的漸變函數(shù)
}).start();
}
/**
* @mark 位移
*/
TransHandle(){
this.startTrans();
}
startTrans() {
Animated.timing(this.state.trans, {
toValue: {
x: 100,
y: 100
},
duration: 2000,
}).start();
}
/**
* @mark 旋轉(zhuǎn)并且持續(xù)進(jìn)行動畫
*/
RotationHandle(){
this.startRotation();
}
startRotation(){
this.state.rotation.setValue(0);
Animated.timing(this.state.rotation, {
toValue: 1, //屬性目標(biāo)值
duration: 2000 //動畫執(zhí)行時間
}).start(() => this.RotationHandle()); //執(zhí)行動畫
}
/**
* @mark 縮放+spring摩擦力
*/
ScaleHandle(){
this.startScale();
}
startScale(){
Animated.spring(this.state.scale, {
toValue: 2, //屬性目標(biāo)值
duration: 500,
friction: 5, //摩擦力 (越小 振幅越大)
tension: 1000, //拉力
}).start(); //執(zhí)行動畫
/*Animated.timing(this.state.scale, {
toValue: 2,
duration: 500,
}).start();*/
}
/**
* @mark 滾動
*/
LeftHandle(){
this.startLeft();
}
startLeft(){
Animated.timing(this.state.left, {
toValue: 1,
duration: 3000,
}).start();
}
//自定義代碼區(qū)結(jié)束
/**
* @mark render
*/
render() {
return <View style={styles.AnimatedDeomo}>
<Animated.View // 可選的基本組件類型: Image, Text, View(可以包裹任意子View)
style = {{alignItems: 'center',justifyContent: 'center',width:Theme.size.width,height:Theme.size.height/2,
opacity: this.state.fadeOutOpacity,
//可以修改成Left 豪硅,Right伪很,top幸缕,進(jìn)行位移轉(zhuǎn)換
bottom:this.state.left.interpolate({
inputRange:[0,1],
outputRange:[0, Theme.size.width/2]
}),
transform:[
{
rotateX: this.state.rotation.interpolate({
inputRange:[0,1],
outputRange:['0deg','360deg']
})
},
{scale: this.state.scale}
]}}>
<Image resizeMode="cover" style={{width:40,height:40,}} source = {require("../../imgs/logo.png")}
/>
</Animated.View >
<Button
fontSize={Theme.fontSize.max}
buttonStyle={styles.loginBtn}
onPress={this.OpacityHandle.bind(this)}
title='淡入淡出'
/>
<Button
fontSize={Theme.fontSize.max}
buttonStyle={styles.loginBtn}
onPress={this.TransHandle.bind(this)}
title='位移'
/>
<Button
fontSize={Theme.fontSize.max}
buttonStyle={styles.loginBtn}
onPress={this.RotationHandle.bind(this)}
title='旋轉(zhuǎn)'
/>
<Button
fontSize={Theme.fontSize.max}
buttonStyle={styles.loginBtn}
onPress={this.ScaleHandle.bind(this)}
title='縮放'
/>
<Button
fontSize={Theme.fontSize.max}
buttonStyle={styles.loginBtn}
onPress={this.LeftHandle.bind(this)}
title='滾動'
/>
</View>
}
}
//@mark style
const styles = StyleSheet.create({
AnimatedDeomo: {
flex:1
},
loginBtn:{
marginTop:Theme.padding.less,
backgroundColor:Theme.color.orange,
borderRadius:Theme.radius.small
}
});
通過上文的講解漠烧,相信讀者已經(jīng)對如何用Animated創(chuàng)建動畫有了最基本的認(rèn)識梆掸。而有些時候栋烤,我們需要根據(jù)Scroll或者手勢來手動的控制動畫的過程。這就是我接下來要講的股淡。
手動控制動畫的核心是Animated.event,
這里的Aniamted.event的輸入是一個數(shù)組,用來做數(shù)據(jù)綁定
比如,
ScrollView中
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: this.state.xOffset}}}]//把contentOffset.x綁定給this.state.xOffset
)}
export default class ScrollAnimated extends React.Component {
/***
* default props value
* @mark propTypes 默認(rèn)屬性值
*/
static defaultProps = {}
/***
* props types for helper text
* @mark propTypes 屬性類型
*/
static propTypes = {}
/**
* @mark state
*/
state = {
xOffset: new Animated.Value(0)
}
/**
* @mark constructor
*/
constructor(props) {
super(props);
}
/**
* @mark 組件聲明周期區(qū)域
*/
/**
* @mark 第一次加載 只運行一次
*/
componentDidMount() {
}
//聲明周期代碼結(jié)束
/**
* @mark 自定義代碼區(qū)
*/
//自定義代碼區(qū)結(jié)束
/**
* @mark render
*/
render() {
return <View style={styles.ScrollAnimated}>
<ScrollView
style={{height: Theme.size.height, width: Theme.size.width}}//設(shè)置大小
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.xOffset}}}]//把contentOffset.x綁定給this.state.xOffset
)}
scrollEventThrottle={100}//onScroll回調(diào)間隔
>
<Image source={require('../../imgs/1.png')} style={{height: Theme.size.height, width: Theme.size.width}}
resizeMode="cover"/>
<Image source={require('../../imgs/2.png')} style={{height: Theme.size.height, width: Theme.size.width}}
resizeMode="cover"/>
<Image source={require('../../imgs/3.png')} style={{height: Theme.size.height, width: Theme.size.width}}
resizeMode="cover"/>
</ScrollView>
<Animated.View // 可選的基本組件類型: Image, Text, View(可以包裹任意子View)
style = {[ styles.titleView,{ opacity:this.state.xOffset.interpolate({//映射到0.0,1.0之間
inputRange: [0,Theme.size.height],
outputRange: [0.0, 1.0]
}),
}]}>
<Text style={{color:Theme.color.white,fontSize:15,textAlign:'center'}}>標(biāo)題</Text>
</Animated.View >
</View>
}
}
//@mark style
const styles = StyleSheet.create({
ScrollAnimated: {
},
titleView:{
alignItems: 'center',
justifyContent: 'center',
width:Theme.size.width,
height:40,
backgroundColor:Theme.color.orange,
position: "absolute",
top: 0,
left: 0
}
});