React-Native: регулятор Slider переходит в случайное положение при использовании diffClamp и нескольких слайдеров - PullRequest
2 голосов
/ 10 апреля 2020

У меня довольно досадная проблема при разработке пользовательского компонента ползунка в реактивном. При использовании только одного слайдера в моем приложении все в порядке. Но если я добавляю более одного слайдера, начинается проблема: если сначала использовать один слайдер, а затем, после завершения анимации, снова использовать тот же слайдер, все в порядке. Но если я использую другой слайдер после первого, а затем снова использую первый, ручка слайдера переходит в случайное положение. Если я не использую функцию "diffClamp" из response-native-reanimated, то проблема не возникает, даже с несколькими ползунками. Но мне нужен diffClamp, чтобы ограничить пространство для ручки слайдера. Я не могу понять, почему компонент ведет себя так. Я использую библиотеку реагировать-нативно-реанимированную, а также библиотеку реагировать-нативно-линейный градиент для фона слайдера.

Ниже приведен минимальный рабочий пример:

CustomSlider. js:


    export default class CustomSlider extends Component {

    constructor(){
        super();

        this.dragX = new Value(0);

        this.offsetX = new Value(0);
        this.gestureState = new Value(State.UNDETERMINED);


        this.transX = diffClamp(cond(
            eq(this.gestureState, State.ACTIVE),
            add(this.offsetX, this.dragX), 
            set(this.offsetX, add(this.offsetX, this.dragX))
        ), 0, SliderStyleSheet.linearGradient.width-30);

        this.gestureHandler = event([
            {
                nativeEvent: {
                    translationX: this.dragX,
                    state: this.gestureState
                }
            }
        ]) 

    }
    logValue(){
        console.log(this.gestureHandler.x)
    }
    render(){
        return(
            <View style={{marginTop: 15}}>
                <View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
                    <Image source={require('../images/CompSigSmile5.png')} style={this.props.imageStyle}/>
                    <Image source={require('../images/CompSigSmile4.png')} style={this.props.imageStyle}/>
                    <Image source={require('../images/CompSigSmile3.png')} style={this.props.imageStyle}/>
                    <Image source={require('../images/CompSigSmile2.png')} style={this.props.imageStyle}/>  
                    <Image source={require('../images/CompSigSmile1.png')} style={this.props.imageStyle}/>
                </View>
                <View>
                    <LinearGradient start={{x:0, y:0}} end={{x:3.5, y:0}} colors={this.props.colors} style={SliderStyleSheet.linearGradient}>
                        <PanGestureHandler style={[{height: SliderStyleSheet.linearGradient.height}]} onGestureEvent={this.gestureHandler} onHandlerStateChange={this.gestureHandler} maxPointers={1}>
                            <Animated.View style={[{...StyleSheet.absoluteFillObject, width: SliderStyleSheet.linearGradient.height, height: SliderStyleSheet.linearGradient.height}, {transform: [{translateX: this.transX}]}]} >
                                <CustomSliderButton buttonColor={this.props.buttonColor}></CustomSliderButton>
                            </Animated.View>
                        </PanGestureHandler>
                    </LinearGradient>  
                </View>  
            </View>
        );
    }
}

Приложение. js:

export default class SliderTestApp extends Component {
  constructor(){
    super();
  }
  render() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <CustomSlider output={"slider1"} colors={[SliderStyleSheet.white.color, SliderStyleSheet.red.color]} imageStyle={SliderStyleSheet.imageStyle} buttonColor={SliderStyleSheet.red.color}></CustomSlider>
        <CustomSlider output={"slider1"} colors={[SliderStyleSheet.white.color, SliderStyleSheet.red.color]} imageStyle={SliderStyleSheet.imageStyle} buttonColor={SliderStyleSheet.red.color}></CustomSlider>
        <CustomSlider output={"slider1"} colors={[SliderStyleSheet.white.color, SliderStyleSheet.red.color]} imageStyle={SliderStyleSheet.imageStyle} buttonColor={SliderStyleSheet.red.color}></CustomSlider>
        <CustomSlider output={"slider1"} colors={[SliderStyleSheet.white.color, SliderStyleSheet.red.color]} imageStyle={SliderStyleSheet.imageStyle} buttonColor={SliderStyleSheet.red.color}></CustomSlider>
        <CustomSlider output={"slider1"} colors={[SliderStyleSheet.white.color, SliderStyleSheet.red.color]} imageStyle={SliderStyleSheet.imageStyle} buttonColor={SliderStyleSheet.red.color}></CustomSlider>
        <CustomSlider output={"slider1"} colors={[SliderStyleSheet.white.color, SliderStyleSheet.red.color]} imageStyle={SliderStyleSheet.imageStyle} buttonColor={SliderStyleSheet.red.color}></CustomSlider>
      </View>
    );
  }
}

SliderStyleSheet. js:

export default StyleSheet.create({
    linearGradient: {
        height: 30,
        width: 150,
        borderRadius: 5,
        marginTop: 10
    }, 
    sliderButtonStyle: {
        borderRadius: 8,
        borderColor: "white",
        borderWidth: 2,
    },
    imageStyle: {
        height: 15,
        width: 15,
    },
    red: {
        color: 'rgba(200,59,62, 0.5)'
    },
    green: {
        color: 'rgba(40,148,72, 2.0)'
    },
    blue: {
        color: 'rgba(62,108,177, 0.5)'
    },
    yellow: {
        color: 'rgba(242,205,55, 0.5)'
    },
    orange: {
        color: 'rgba(208,102,28, 0.5)'
    },
    grey: {
        color: 'rgba(134,134,134, 0.5)'
    },
    white: {
        color: 'rgba(255,255,255, 0.5)'
    },
})

Возможно, кто-то сталкивался с такой же проблемой. Я был бы очень благодарен, если бы кто-то мог ответить на это.

Спасибо и привет!

1 Ответ

0 голосов
/ 17 апреля 2020

Я адаптировал конструктор класса CustomSlider. js следующим образом:

constructor(){
    super();

    this.dragX = new Value(0);

    this.offsetX = new Value(0);
    this.gestureState = new Value(State.UNDETERMINED);

    this.testlog = this.testlog.bind(this)

    this.gestureHandler = event([
        {
            nativeEvent: {
                translationX: this.dragX,
                state: this.gestureState
            }
        }
    ])
    this.transX = interpolate(cond(
        eq(this.gestureState, State.ACTIVE),
        add(this.offsetX, this.dragX), 
        set(this.offsetX, interpolate(add(this.offsetX, this.dragX), {
            inputRange: [0, SliderStyleSheet.linearGradient.width-SliderStyleSheet.linearGradient.height],
            outputRange: [0, SliderStyleSheet.linearGradient.width-SliderStyleSheet.linearGradient.height], 
            extrapolateRight: 'clamp', 
            extrapolateLeft: 'clamp'
        }))), {
            inputRange: [0, SliderStyleSheet.linearGradient.width-SliderStyleSheet.linearGradient.height], 
            outputRange: [0, SliderStyleSheet.linearGradient.width-SliderStyleSheet.linearGradient.height], 
            extrapolateRight: 'clamp',
            extrapolateLeft: 'clamp'
    })


}

Я использовал функцию interpoalte () вместо diffClamp (), и это помогло мне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...