wix / react-native-ui-lib

UI Components Library for React Native
https://wix.github.io/react-native-ui-lib/
MIT License
6.53k stars 712 forks source link

Incubator.Slider - Incubator.Slider can't update render when i change thumbTintColor #3198

Closed 5201314999 closed 1 month ago

5201314999 commented 2 months ago

Description

Incubator.Slider can't update render when i change thumbTintColor

Related to

Steps to reproduce

Expected behavior

Actual behavior

More Info

Code snippet

import React, { useEffect, useState } from 'react';
import { View, StyleSheet } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { Incubator } from 'react-native-ui-lib';

const COLORS = [
  '#F00',
  '#FF7500',
  '#F6F400',
  '#03FF0F',
  '#00FDFB',
  '#00BEFF',
  '#0B0AFF',
  '#FF00E0',
  '#FF0030',
];
const ColorSlider = () => {
  const [sliderValue, setSliderValue] = useState(0);

  // 将 slider 值转换为颜色值
  const getBackgroundColor = (value) => {
    const red = Math.floor((255 * value) / 255);
    const green = Math.floor((255 * (255 - value)) / 255);
    const blue = Math.floor((255 * (value / 2)) / 255);
    return `rgb(${red},${green},${blue})`;
  };

  const [thumbTintColor, setThumbTintColor] = useState('red');
  const [key, setKey] = useState(0);

  const onValueChange = (value: number) => {
    const color = getColorAtPosition(value);
    console.log('color:', color);
    setThumbTintColor(color);
    key === 0 ? setKey(1) : setKey(0);
  };

  const getColorAtPosition = (positionX: number) => {
    const relativePosition = positionX / 100;
    const colorIndex = Math.floor(relativePosition * (COLORS.length - 1));
    const color1 = COLORS[colorIndex];
    const color2 = COLORS[colorIndex + 1];
    const color1Pos = colorIndex / (COLORS.length - 1);
    const color2Pos = (colorIndex + 1) / (COLORS.length - 1);
    const factor = (relativePosition - color1Pos) / (color2Pos - color1Pos);
    return interpolateColor(color1, color2, factor);
  };

  const interpolateColor = (color1: string, color2: string, factor: number) => {
    const hexToRgb = (hex: string) => {
      const bigint = parseInt(hex.replace('#', ''), 16);
      const r = (bigint >> 16) & 255;
      const g = (bigint >> 8) & 255;
      const b = bigint & 255;
      return [r, g, b];
    };

    const rgbToHex = (r: number, g: number, b: number) =>
      '#' +
      ((1 << 24) + (r << 16) + (g << 8) + b)
        .toString(16)
        .slice(1)
        .toUpperCase();

    const [r1, g1, b1] = hexToRgb(color1);
    const [r2, g2, b2] = hexToRgb(color2);

    const r = Math.round(r1 + (r2 - r1) * factor);
    const g = Math.round(g1 + (g2 - g1) * factor);
    const b = Math.round(b1 + (b2 - b1) * factor);

    return rgbToHex(r, g, b);
  };

  return (
    <>
      <Incubator.Slider
        // key={key}
        trackStyle={{
          height: 10,
          borderRadius: 5,
        }}
        disableActiveStyling
        renderTrack={() => (
          <LinearGradient
            colors={COLORS}
            locations={[0, 0.1, 0.2, 0.36, 0.5, 0.54, 0.67, 0.83, 1]}
            // background: linear-gradient(90deg, #F00 0%, #FF7500 10.16%, #F6F400 19.89%, #03FF0F 36.7%, #00FDFB 49.67%, #00BEFF 53.39%, #0B0AFF 67.08%, #FF00E0 83.29%, #FF0030 100%);
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            style={styles.gradient}
          ></LinearGradient>
        )}
        thumbStyle={{
          width: 16,
          height: 16,
          borderRadius: 8,
          borderWidth: 2,
          borderColor: '#ffffff',
        }}
        thumbTintColor={thumbTintColor}
        value={sliderValue}
        minimumValue={0}
        maximumValue={100}
        onValueChange={onValueChange}
      />
      <View
        style={{ width: 10, height: 10, backgroundColor: thumbTintColor }}
      ></View>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  slider: {
    width: 300,
    height: 40,
  },
  gradient: {
    width: '100%',
    height: 10,
    borderRadius: 5,
  },
  text: {
    fontSize: 18,
    marginBottom: 20,
  },
});

export default ColorSlider;

Screenshots/Video

image

Environment

Affected platforms

5201314999 commented 2 months ago
image

sometimes it will not right offset when tap the thumb top border to slide

5201314999 commented 2 months ago

when step={1} onValueChange will trigger in serveral times but their values are the same,maybe the value is 1.2 or 1.3, they all are the 1

5201314999 commented 2 months ago
image
5201314999 commented 2 months ago
image

I also encountered a problem where the throttle value is in the wrong order. and I fixed it with requestAmination . My usage scene is onValueChangeThrottled to update all shapes of the canvas color and size .

 LOG  00000000: 16.55513307984791
 LOG  throttle: 16.55513307984791
 LOG  00000000: 17.44486692015209
 LOG  00000000: 18.53231939163498
 LOG  00000000: 19.125475285171103
 LOG  00000000: 19.619771863117872
 LOG  throttle: 19.619771863117872
 LOG  00000000: 19.817490494296578
 LOG  00000000: 20.015209125475288
 LOG  00000000: 20.11406844106464
 LOG  throttle: 19.125475285171103
 LOG  throttle: 20.11406844106464
adids1221 commented 2 months ago

Hi, fix PR is in review.

5201314999 commented 2 months ago

Hi, fix PR is in review.

I'm very grateful to you, but I think there are still some other mistakes in it.

adids1221 commented 1 month ago

@5201314999 If you other issues with the component please open relevant issue, with code and description. The fix PR merged I'm closing the issue.