Material-UI 滑块 - 使用比例更改值

Har*_*M V 4 reactjs material-design material-ui

我想在滑块上显示从 1000 到 1M 的范围并添加以下标记

const followersMarks = [
    {
      value: 1000,
      label: '1k',
    },
    {
      value: 5000,
      label: '5k',
    },
    {
      value: 10000,
      label: '10k',
    },
    {
      value: 25000,
      label: '25k',
    },
    {
      value: 50000,
      label: '50k',
    },
    {
      value: 100000,
      label: '100k',
    },
    {
      value: 250000,
      label: '250k',
    },
    {
      value: 500000,
      label: '500k',
    },
    {
      value: 1000000,
      label: '1M',
    },
  ];
Run Code Online (Sandbox Code Playgroud)

我添加如下

<Form.Group controlId="formGridState">
              <Form.Label className="mb-15">Followers Range</Form.Label>
              <Slider
                value={followersRange}
                onChange={handleChangeFollowersRange}
                valueLabelDisplay="auto"
                aria-labelledby="range-slider"
                step="1000"
                valueLabelDisplay="on"
                marks={followersMarks}
                min={1000}
                max={1000000}
              />
            </Form.Group>
Run Code Online (Sandbox Code Playgroud)

这是结果:

在此处输入图片说明

我需要什么?

由于在范围开始时我显示了更多标记,因此易读性和用户体验都很糟糕。有没有办法用scale这种方式来显示范围,即需要 50-60% 的空间来显示前 25% 的值,然后将其余的值隔开?

Rya*_*ell 5

下面是执行此操作的一种方法的工作示例。需要注意的关键问题是,对于价值观minmaxstep,和value(包括valuemarks)是线性值。scale然后该函数将这些转换为您想要显示的非线性值。

import React from "react";
import Typography from "@material-ui/core/Typography";
import Slider from "@material-ui/core/Slider";

const followersMarks = [
  {
    value: 0,
    scaledValue: 1000,
    label: "1k"
  },
  {
    value: 25,
    scaledValue: 5000,
    label: "5k"
  },
  {
    value: 50,
    scaledValue: 10000,
    label: "10k"
  },
  {
    value: 75,
    scaledValue: 25000,
    label: "25k"
  },
  {
    value: 100,
    scaledValue: 50000,
    label: "50k"
  },
  {
    value: 125,
    scaledValue: 100000,
    label: "100k"
  },
  {
    value: 150,
    scaledValue: 250000,
    label: "250k"
  },
  {
    value: 175,
    scaledValue: 500000,
    label: "500k"
  },
  {
    value: 200,
    scaledValue: 1000000,
    label: "1M"
  }
];

const scale = value => {
  const previousMarkIndex = Math.floor(value / 25);
  const previousMark = followersMarks[previousMarkIndex];
  const remainder = value % 25;
  if (remainder === 0) {
    return previousMark.scaledValue;
  }
  const nextMark = followersMarks[previousMarkIndex + 1];
  const increment = (nextMark.scaledValue - previousMark.scaledValue) / 25;
  return remainder * increment + previousMark.scaledValue;
};

function numFormatter(num) {
  if (num > 999 && num < 1000000) {
    return (num / 1000).toFixed(0) + "K"; // convert to K for number from > 1000 < 1 million
  } else if (num >= 1000000) {
    return (num / 1000000).toFixed(0) + "M"; // convert to M for number from > 1 million
  } else if (num < 900) {
    return num; // if value < 1000, nothing to do
  }
}

export default function NonLinearSlider() {
  const [value, setValue] = React.useState(1);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  return (
    <div>
      <Typography id="non-linear-slider" gutterBottom>
        Followers
      </Typography>
      <Slider
        style={{ maxWidth: 500 }}
        value={value}
        min={0}
        step={1}
        max={200}
        valueLabelFormat={numFormatter}
        marks={followersMarks}
        scale={scale}
        onChange={handleChange}
        valueLabelDisplay="auto"
        aria-labelledby="non-linear-slider"
      />
      <Typography>Value: {scale(value)}</Typography>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

编辑滑块比例


这是一个类似的示例,但针对范围滑块进行了修改:

import React from "react";
import Typography from "@material-ui/core/Typography";
import Slider from "@material-ui/core/Slider";

const followersMarks = [
  {
    value: 0,
    scaledValue: 1000,
    label: "1k"
  },
  {
    value: 25,
    scaledValue: 5000,
    label: "5k"
  },
  {
    value: 50,
    scaledValue: 10000,
    label: "10k"
  },
  {
    value: 75,
    scaledValue: 25000,
    label: "25k"
  },
  {
    value: 100,
    scaledValue: 50000,
    label: "50k"
  },
  {
    value: 125,
    scaledValue: 100000,
    label: "100k"
  },
  {
    value: 150,
    scaledValue: 250000,
    label: "250k"
  },
  {
    value: 175,
    scaledValue: 500000,
    label: "500k"
  },
  {
    value: 200,
    scaledValue: 1000000,
    label: "1M"
  }
];

const scaleValues = (valueArray) => {
  return [scale(valueArray[0]), scale(valueArray[1])];
};
const scale = (value) => {
  if (value === undefined) {
    return undefined;
  }
  const previousMarkIndex = Math.floor(value / 25);
  const previousMark = followersMarks[previousMarkIndex];
  const remainder = value % 25;
  if (remainder === 0) {
    return previousMark.scaledValue;
  }
  const nextMark = followersMarks[previousMarkIndex + 1];
  const increment = (nextMark.scaledValue - previousMark.scaledValue) / 25;
  return remainder * increment + previousMark.scaledValue;
};

function numFormatter(num) {
  if (num > 999 && num < 1000000) {
    return (num / 1000).toFixed(0) + "K"; // convert to K for number from > 1000 < 1 million
  } else if (num >= 1000000) {
    return (num / 1000000).toFixed(0) + "M"; // convert to M for number from > 1 million
  } else if (num < 900) {
    return num; // if value < 1000, nothing to do
  }
}

export default function NonLinearSlider() {
  const [value, setValue] = React.useState([1, 25]);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  return (
    <div>
      <Typography id="non-linear-slider" gutterBottom>
        Followers
      </Typography>
      <Slider
        style={{ maxWidth: 500 }}
        value={value}
        min={0}
        step={1}
        max={200}
        valueLabelFormat={numFormatter}
        marks={followersMarks}
        scale={scaleValues}
        onChange={handleChange}
        valueLabelDisplay="auto"
        aria-labelledby="non-linear-slider"
      />
      <Typography>Values: {JSON.stringify(scaleValues(value))}</Typography>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

编辑滑块比例

  • 哇,非常感谢您耐心地将这些代码放在一起。我非常感激。 (2认同)