Почему эта анимация не работает правильно на первом проходе, но работает на всех последующих проходах?(Реагируй Родной) - PullRequest
0 голосов
/ 28 февраля 2019

Используя React Native, я пытаюсь сделать анимированное слайд-шоу с 3 циклами.По какой-то причине он не работает правильно в первом цикле, но делает это потом.

Проблема в том, что во второй раз появляются драконы (первое изображение), это происходит мгновенно, потому что this.state.imageThreeOpacity, похоже, не оживляет в первый раз.

Однако по мере продолжения видео вы увидите, что оно исправляет себя.

Вот видео моего слайд-шоу в его текущем состоянии .: https://streamable.com/tpjcz

Вотмой код компонента.Цикл анимации с рекурсивной функцией animate:

import React, { Component } from 'react';
import {
    StyleSheet,
    Image,
    View,
    Dimensions,
    Animated,
} from 'react-native';
import _ from 'underscore';
import imageCacheHoc from 'react-native-image-cache-hoc';

const CacheableImage = imageCacheHoc( Image, {
    validProtocols: [ 'http', 'https', '' ]
} );

const animationDistance = 250;

export default class ImageIntro extends Component {

    constructor() {
        super();

        this.state = {
            imageOneOpacity: new Animated.Value( 1 ),
            imageTwoOpacity: new Animated.Value( 1 ),
            imageThreeOpacity: new Animated.Value( 1 ),
            imageOneZIndex: 3,
            imageTwoZIndex: 2,
            imageThreeZIndex: 1,
            imageOneTranslateX: new Animated.Value( -( animationDistance / 2 ) ),
            imageOneTranslateY: new Animated.Value( 0 ),
            imageTwoTranslateX: new Animated.Value( animationDistance / 2 ),
            imageTwoTranslateY: new Animated.Value( -( animationDistance / 2 ) ),
            imageThreeTranslateX: new Animated.Value( 0 ),
            imageThreeTranslateY: new Animated.Value( animationDistance / 2 ),
        };
    }

    componentDidMount() {
        this.animate( true );
    }

    animate( firstPass ) {    
        let {
                imageOneOpacity,
                imageTwoOpacity,
                imageThreeOpacity,
                imageOneTranslateX,
                imageOneTranslateY,
                imageTwoTranslateX,
                imageTwoTranslateY,
                imageThreeTranslateX,
                imageThreeTranslateY
            } = this.state;

        const duration = 2000;
        const delay = 1500;

        setTimeout( () => {
            this.animate( false );
        }, ( duration * 3 ) - ( ( duration - delay ) * 3 ) );

        Animated.parallel(
            [
                Animated.timing(
                    imageOneTranslateX, {
                        toValue: animationDistance / 2,
                        useNativeDriver: true,
                        duration: duration,
                    }
                ),
                Animated.timing(
                    imageOneOpacity, {
                        toValue: 0,
                        useNativeDriver: true,
                        delay: delay,
                        duration: duration - delay,
                    }
                ),
            ]
        ).start( () => {
            Animated.timing(
                imageOneTranslateX, {
                    toValue: -( animationDistance / 2 ),
                    useNativeDriver: true,
                    duration: 0,
                }
            ).start();
        } );

        Animated.parallel(
            [
                Animated.timing(
                    imageTwoTranslateX, {
                        toValue: -( animationDistance / 2 ),
                        useNativeDriver: true,
                        duration: duration,
                        delay: delay,
                    },
                ),
                Animated.timing(
                    imageTwoTranslateY, {
                        toValue: ( animationDistance / 2 ),
                        useNativeDriver: true,
                        duration: duration,
                        delay: delay,
                    },
                ),
                Animated.timing(
                    imageTwoOpacity, {
                        toValue: 0,
                        useNativeDriver: true,
                        delay: delay * 2,
                        duration: duration - delay,
                    }
                ),
            ]
        ).start( () => {
            Animated.timing(
                imageTwoTranslateX, {
                    toValue: ( animationDistance / 2 ),
                    useNativeDriver: true,
                    duration: 0,
                }
            ).start();
            Animated.timing(
                imageTwoTranslateY, {
                    toValue: -( animationDistance / 2 ),
                    useNativeDriver: true,
                    duration: 0,
                }
            ).start();
            this.setState( { imageThreeZIndex: 4 }, () => {
                Animated.timing(
                    imageOneOpacity, {
                        toValue: 1,
                        useNativeDriver: true,
                        duration: 0,
                    }
                ).start();
                Animated.timing(
                    imageTwoOpacity, {
                        toValue: 1,
                        useNativeDriver: true,
                        duration: 0,
                    }
                ).start();
            } );
        } );

        Animated.parallel(
            [
                Animated.timing(
                    imageThreeTranslateY, {
                        toValue: -( animationDistance / 2 ),
                        useNativeDriver: true,
                        duration: duration,
                        delay: delay * 2,
                    }
                ),
                Animated.timing(
                    imageThreeOpacity, {
                        toValue: 0,
                        useNativeDriver: true,
                        delay: delay * 3,
                        duration: duration - delay,
                    }
                ),
            ]
        ).start( () => {
            Animated.timing(
                imageThreeTranslateY, {
                    toValue: ( animationDistance / 2 ),
                    useNativeDriver: true,
                    duration: 0,
                }
            ).start();

            this.setState( { imageThreeZIndex: 1 }, () => {
                Animated.timing(
                    imageThreeOpacity, {
                        toValue: 1,
                        useNativeDriver: true,
                        duration: 0
                    }
                );
            } );

        } );

    }

    render() {
        const { images } = this.props;

        const outputImages = () => {
            let {
                    imageOneOpacity,
                    imageTwoOpacity,
                    imageThreeOpacity,
                    imageOneZIndex,
                    imageTwoZIndex,
                    imageThreeZIndex,
                    imageOneTranslateX,
                    imageOneTranslateY,
                    imageTwoTranslateX,
                    imageTwoTranslateY,
                    imageThreeTranslateX,
                    imageThreeTranslateY
                } = this.state;

            const animationProps = [
                [ imageOneOpacity, imageOneTranslateX, imageOneTranslateY ],
                [ imageTwoOpacity, imageTwoTranslateX, imageTwoTranslateY ],
                [ imageThreeOpacity, imageThreeTranslateX, imageThreeTranslateY ]
            ];

            let output = [];

            _.each( images, ( image, index ) => {
                output.push(
                    <Animated.View key={ `intro-image-${index}` } style={ [ styles.imageWrap, {
                        zIndex: [ imageOneZIndex, imageTwoZIndex, imageThreeZIndex ][ index ],
                        opacity: animationProps[ index ][ 0 ],
                        transform: [
                            { translateX: animationProps[ index ][ 1 ] },
                            { translateY: animationProps[ index ][ 2 ] }
                        ]
                    } ] }>
                        <CacheableImage style={ styles.image }
                                        permanent={ true }
                                        source={ { uri: image } }/>
                    </Animated.View>
                )
            } );

            return output;
        };

        return (
            <View style={ [ styles.container ] }>
                { outputImages() }
            </View>
        );
    }
}

const { width, height } = Dimensions.get( 'window' );

const styles = StyleSheet.create( {
    container: {
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
        zIndex: 1
    },
    imageWrap: {
        position: 'absolute',
        backgroundColor: 'blue',
        top: -( animationDistance / 2 ),
        left: -( animationDistance / 2 ),
        width: width + animationDistance,
        height: height + animationDistance
    },
    image: {
        width: width + animationDistance,
        height: height + animationDistance
    }
} );

Кто-нибудь видит, что это вызывает?

...