RN中实现类似Android中的帧动画及坑
2018-11-22 本文已影响128人
咸鱼Jay
一、前言
在Android中实现帧动画很简单,定义一个animation-list就可以直接使用了,例如:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item
android:drawable="@drawable/custom_clock_time_01"
android:duration="1000">
</item>
<item
android:drawable="@drawable/custom_clock_time_02"
android:duration="1000">
</item>
<item
android:drawable="@drawable/custom_clock_time_03"
android:duration="1000">
</item>
<item
android:drawable="@drawable/custom_clock_time_04"
android:duration="1000">
</item>
二、实现
但是在RN中应该是没有这种简单的方法吧,不过也可以实现类似的效果,原理就是定义一个数组把帧动画需要的那些图片放入数组汇总,然后使用一个定时器setInterval
不断的展示这几张图片,就可以了。
实现CockView组件
import React, {Component} from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image
} from 'react-native';
var LoadingImgs = [
require('./img/custom_clock_time_01.png'),
require('./img/custom_clock_time_02.png'),
require('./img/custom_clock_time_03.png'),
require('./img/custom_clock_time_04.png'),
];
export default class CockView extends Component {
//设置默认属性
static defaultProps = {
time: 60
}
constructor(props) {
super(props);
console.log("constructor==")
this.state = {
loadImgIndex: 0,
time: props.time
}
}
componentDidMount() {
if (this.timer === undefined) {
this.timer = setInterval(() => {
let i = this.state.loadImgIndex + 1;
i = i % LoadingImgs.length;
this.setState({
loadImgIndex: i,
time: this.state.time - 1
})
if (this.state.time === 0) {
clearInterval(this.timer);
}
console.log("i==",i)
}, 1000);
}
}
componentWillUnmount() {
this.timer && clearInterval(this.timer);
}
render() {
return (
<View style={{
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row'
}}>
<View style={{marginLeft: 20}}>
<Text style={{fontSize: 30}}>{this.state.time} 秒</Text>
</View>
</View>
)
}
}
最后在其他地方使用这个组件就可以了, time是指定倒计时的时间
<CockView time={10}/>
三、问题
但是有个小bug,就是刚进入界面后,第一次循环,图片会闪烁,这是怎么回事呢?这个问题纠结了我好久,无意之间我直接使用Image控件一个一个加载每个图片,他就不会闪烁了,
render() {
return (
<View style={{
justifyContent: 'center',
alignItems: 'center',
}}>
<Image style={{width: 80, height: 80}}
source={require('./img/custom_clock_time_01.png')} />
<Image style={{width: 80, height: 80}}
source={require('./img/custom_clock_time_02.png')} />
<Image style={{width: 80, height: 80}}
source={require('./img/custom_clock_time_03.png')} />
<Image style={{width: 80, height: 80}}
source={require('./img/custom_clock_time_04.png')} />
<Image style={{width: 80, height: 80}}
source={LoadingImgs[this.state.loadImgIndex]} />
<View style={{marginLeft: 20}}>
<Text style={{fontSize: 30}}>{this.state.time} 秒</Text>
</View>
</View>
)
}
从这我估计是第一次循环的时候,这四张都还没有缓存,所有有闪烁现象。
问题找到了,但是我页面中不可能把这四张都显示出来吧,有没有像Android中,只加载控件却不显示的方法呢?经过我多方查找貌似没有。难道这个没有问题了?好在我突然想到加载这四张图片,但是把这个Image的宽高都设置为0试一试,果然可以了
render() {
return (
<View style={{
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row'
}}>
<Image style={{width: 0, height: 0}}
source={require('./img/custom_clock_time_01.png')} />
<Image style={{width: 0, height: 0}}
source={require('./img/custom_clock_time_02.png')} />
<Image style={{width: 0, height: 0}}
source={require('./img/custom_clock_time_03.png')} />
<Image style={{width: 0, height: 0}}
source={require('./img/custom_clock_time_04.png')} />
<Image style={{width: 80, height: 80}}
source={LoadingImgs[this.state.loadImgIndex]} />
<View style={{marginLeft: 20}}>
<Text style={{fontSize: 30}}>{this.state.time} 秒</Text>
</View>
</View>
)
}
哈哈,虽然有点投机取巧,先这么用吧!