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>
        )
    }

哈哈,虽然有点投机取巧,先这么用吧!

源代码地址

上一篇下一篇

猜你喜欢

热点阅读