为什么我的Animated视图不能在React Native中停留在正确的位置?

时间:2018-08-03 14:25:10

标签: reactjs react-router

我创建了一个“圆棒”(一组视图),随着图像的移动从灰色切换为黄色。圆开始正确变形,但然后返回第一个点,而不是转到下一个圆点以指示您在下一张图像上。无论如何,黄色圆圈始终会回到第一位。有谁知道为什么会这样?我如何才能留在下一个景点?

请观看我制作的这段视频:https://youtu.be/BCaSgNexPAs

这是我创建和处理圆形视图转换的方式:

    let circleArray = [];

    if (this.state.imgArray) {
        this.state.imgArray.forEach((val, i) => {
            const scrollCircleVal = this.imgXPos.interpolate({
                inputRange: [deviceWidth * (i - 1), deviceWidth * (i + 1)],
                outputRange: [-8, 8],
                extrapolate: 'clamp',
            });

            const thisCircle = (
                <View
                    key={'circle' + i}
                    style={[
                        styles.track,
                        {
                            width: 8,
                            height: 8,
                            marginLeft: i === 0 ? 0 : CIRCLE_SPACE,
                            borderRadius: 75

                        },
                    ]}
                >
                    <Animated.View
                        style={[
                            styles.circle,
                            {
                                width: 8,
                                height: 8,
                                borderRadius: 75,
                                transform: [
                                    {translateX: scrollCircleVal},
                                ],
                                backgroundColor: '#FFD200'
                            },
                        ]}
                    />
                </View>
            );
            circleArray.push(thisCircle)
        });
    }

这是我处理图像滑动方式的代码:

handleSwipe = (indexDirection) => {
    if (!this.state.imgArray[this.state.imgIndex + indexDirection]) {
        Animated.spring(this.imgXPos, {
            toValue: 0
        }).start();
        return;
    }

    this.setState((prevState) => ({
        imgIndex: prevState.imgIndex + indexDirection
    }), () => {
        this.imgXPos.setValue(indexDirection * this.width);
        Animated.spring(this.imgXPos, {
            toValue: 0
        }).start();
    });
}

imgPanResponder = PanResponder.create({
    onStartShouldSetPanResponder: () => true,
    onPanResponderMove: (e, gs) => {
        this.imgXPos.setValue(gs.dx);
    },
    onPanResponderRelease: (e, gs) => {
        this.width = Dimensions.get('window').width;
        const direction = Math.sign(gs.dx);

        if (Math.abs(gs.dx) > this.width * 0.4) {
            Animated.timing(this.imgXPos, {
                toValue: direction * this.width,
                duration: 250
            }).start(() => this.handleSwipe(-1 * direction));
        } else {
            Animated.spring(this.imgXPos, {
                toValue: 0
            }).start();
        }
    }
});

HTML:

<Animated.Image 
    {...this.imgPanResponder.panHandlers}
    key={'image' + this.state.imgIndex}
    style={{left: this.imgXPos, height: '100%', width: '100%', borderRadius: 7}}
    resizeMethod={'scale'}
    resizeMode={'cover'}
    source={{uri: this.state.imgArray[this.state.imgIndex]}}
/>
<View style={styles.circleContainer}>
    {circleArray}
</View>

2 个答案:

答案 0 :(得分:2)

一开始很难获得代码,因为它们都在同一位置。

我首先建议将代码分成较小的部分:ImageView,CirclesView

现在,在完成此操作之后,我想尝试使CirclesView变得更简单(除非您真的希望将动画视图包含在圆圈内)。

但是从您的代码中,我看不到“ selectedImage”(imgIndex)的区别

因为它具有每个索引的计算功能,但没有引用所选图像。

我认为与当前代码有关的粗略棒球代码:

    let circleArray = [];

    if (this.state.imgArray) {
        this.state.imgArray.forEach((val, i) => {
            const scrollCircleVal = this.imgXPos.interpolate({
                inputRange: [deviceWidth * (i - 1), deviceWidth * (i + 1)],
                outputRange: [-8, 8],
                extrapolate: 'clamp',
            });

            const thisCircle = (
                <View
                    key={'circle' + i}
                    style={[
                        styles.track,
                        {
                            width: 8,
                            height: 8,
                            marginLeft: i === 0 ? 0 : CIRCLE_SPACE,
                            borderRadius: 75

                        },
                    ]}
                >

                   // LOOK AT THIS LINE BELOW

                   {this.state.imgIndex == i &&
                    <Animated.View
                        style={[
                            styles.circle,
                            {
                                width: 8,
                                height: 8,
                                borderRadius: 75,
                                transform: [
                                    {translateX: scrollCircleVal},
                                ],
                                backgroundColor: '#FFD200'
                            },
                        ]}
                    />}
                </View>
            );
            circleArray.push(thisCircle)
        });
    }

签出我在“动画”圆上方添加的“选定”圆的行

答案 1 :(得分:0)

我会同意Tzook的大部分通知...但是从代码(意图)的角度来看,所有圆圈都是动画的(但实际上只有一对受影响-一个隐藏,一个显示)-仅对选定的一个进行动画处理'不给。

我在动画中对数百个“滑块/画廊”进行了动画处理;)-使用上一个/下一个/邻居图像进行动画处理-不应该同时进行动画处理吗?

具有相同宽度的图像(或者当您可以接受它们之间的边距时)很容易,您可以使用更长(当然是循环的?)列表/数组中的3个(甚至只有2个)图像来为容器设置动画。就像虚拟列表滚动一样。

拥有这个工作圈子也将很容易-仅为其中的3个动画:上一个/当前/下一个。

简单的动画很容易-仅在动画结束时交换图像。 f.e.可能看起来更难弹跳效果(当图像滑动到比目标位置更大/更远并且下一幅img应该可见一会儿时),但是您可以在识别方向之后更早地交换它们。