如何登陆用户在图像滑动中点击的图像?

问题描述

我的 React Native 0.64 应用程序使用 react-native-gesture-handler 1.16/react-native-reanimated 2.1 来左右滑动图像。这个想法是当用户单击图库中的图像时,该图像会占据全屏显示,而图库中的其余图像可以通过向左或向右滑动来一张一张地查看。这是滑动有效但有一个问题的完整代码:单击的图像未显示,但图库中的第一张图像始终首先显示。如何登陆用户点击的图片

import React,{ useRef } from "react";
import { Dimensions,StyleSheet,View,Platform } from "react-native";
import Fastimage from 'react-native-fast-image';
import Animated,{
  useAnimatedStyle,useSharedValue,useAnimatedRef,useAnimatedGestureHandler,useAnimatedReaction,withTiming,withSpring,useDerivedValue,} from "react-native-reanimated";
import {
  snapPoint,} from "react-native-redash";
import {
  PanGestureHandler,PinchGestureHandler,State,TouchableOpacity,} from "react-native-gesture-handler";

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

export default Swipe = ({route,navigation}) => {
    const {images,initIndex} = route.params;  //initIndex is the index of image clicked
    console.log("route params swipe ",route.params);
    const index = useSharedValue(initIndex);
    const snapPoints = images.map((_,i) => i * -width);
    const panRef = useAnimatedRef();
    const pinchRef = useAnimatedRef();
    const offsetX = initIndex ? useSharedValue(initIndex * -width) : useSharedValue(0);  //The init offsetX is set according to initIndex a user clicked.
    const translationX = useSharedValue(0);
    const translateX = useSharedValue(0); //if translateX was assgined with offsetX,then swipe stops working
    //for snap in swipe
    const lowVal = useDerivedValue(() => {return (index.value + 1) * -width}); //shared value,with .value
    const highVal = useDerivedValue(() => {return (index.value - 1) * -width});  //shared value,with .value
    const snapPt = (e) => {
        "worklet"; 
        return snapPoint(translateX.value,e.veLocityX,snapPoints);
    };
    
    const panHandler = useAnimatedGestureHandler(
        {
         onStart: () => {
            translateX.value = offsetX.value;  //As soon as a user swipe,this line allow the 
 //image is moved to initIndex-th image. But how to land on the image a user has clicked?
         },onActive: (event) => {
            translateX.value = offsetX.value + event.translationX;
            translationX.value = event.translationX;
         },onEnd: (event) => {
            let val = snapPt(event);
            let sp = Math.min(Math.max(lowVal.value,val),highVal.value);  //clamp in RN redash
            if (event.translationX !== 0) {
                translateX.value = withTiming(sp);
                offsetX.value = translateX.value;
            };
            //update index
            index.value = Math.floor(translateX.value/-width);          
         },},[]
    )

    const swipestyle = useAnimatedStyle(() => {
        return {
            transform: [{ translateX: translateX.value}]
        }
    });

    return (
        <PanGestureHandler
            onGestureEvent={panHandler}
            ref={panRef}
            mindist={10}
            avgtouches
        >
        <Animated.View style={styles.container}>
                <Animated.View
                style={[{width: width * images.length,height,flexDirection: "row"},swipestyle]}
                >
                  
                {images.map((img_source,i) => {
                    const isActive = useDerivedValue(() => {return index.value === i});
                    
                    return (
                    <View key={i} style={styles.picture}>
                        <View style={[
                            styles.image,]}>
                          <TouchableOpacity onPress={() => navigation.goBack()} style={styles.button}>
                            <View style={styles.button}>
                              <Fastimage 
                                          source={{uri:img_source.path}} 
                                          resizeMode={Fastimage.resizeMode.contain} 
                                          style={styles.image}
                              />
                            </View>
                          </TouchableOpacity>
                        </View>
                    </View>
                    );
                })}
                
                </Animated.View>
            </Animated.View>
            </PanGestureHandler>    
    );
}

const styles = StyleSheet.create({
container: {
  ...StyleSheet.absoluteFillObject,backgroundColor: "black",picture: {
  width,overflow: "hidden",image: {
  //...StyleSheet.absoluteFillObject,flex:1,width: undefined,height: undefined,//resizeMode: "cover",button: {
  width: width,height:height,

});

代码的另一个问题是,在滑动图像之前触摸图像时,图像会向左或向右 1/3-1/2 屏幕宽度猛拉。这使得滑动不平滑。我想知道如何消除图像抖动并使滑动从头到尾平滑。

解决方法

为了登陆用户点击的图片,添加了一个 useEffect 钩子:

useEffect(() => {
        translateX.value = offsetX.value;
    },[initIndex]);

onStart 需要完全删除。

图像抖动的原因是错误表示 offsetX 值。 offsetX 应位于屏幕的边界处(屏幕宽度的倍数)。但是,当图像宽度小于屏幕宽度时,offsetX 可能位于图像的边界处,该边界可能会稍微少一点或多一点(取决于是向左滑动还是向右滑动),这会导致图像向左抖动或在最初滑动时正确。在这种情况下,需要将 offsetX 设置为屏幕边框(屏幕宽度的倍数)。