如何在 Material UI Slider 中显示对数刻度

问题描述 投票:0回答:1

我正在制作一个像 https://www.camexcalc.com 上的那样的曝光计算器,但在 React.JS 中重新制作了该网站。我正在使用 Material UI 滑块。当我制作这个滑块时,它是线性显示的,但该系列是对数的,这意味着右侧的数字很少,左侧的数字密度很高。如何覆盖此滑块以采用对数刻度,或者将值沿刻度等距离间隔为字符串而不考虑值?请注意,我不是 React 开发人员,这对我来说都是新鲜事。


const isoValues = [3, 7, 12, 25, 50, 100, 200, 400, 800, 1600, 3200];
const isoMarks = isoValues.map((value) => ({value, label: value.toString()}));
const [iso, setIso] = useState(100);
const handleIsoChange = (event: Event, newValue: number | number[]) => {
    setIso(newValue as number);
};
return(
          <div className="row">
              <div className="col-xs-3 col-sm-2 col-md-4">ISO</div>
              <div className="hidden-xs col-sm-2 col-md-2">
                <label id="IsoDisplay">{iso}</label>
              </div>
              <div className="col-xs-8 col-sm-8 col-md-6">
                <Slider
                  className="slider"
                  id="Iso"
                  min = {isoValues[0]}
                  max = {isoValues[isoValues.length - 1]}
                  step={null}
                  value={iso}
                  onChange={handleIsoChange}
                  marks={isoMarks}

                />
              </div>
)

结果是一个线性刻度,左侧有很多小数字。我想要 ISO 值之间的间距相等

reactjs material-ui
1个回答
0
投票

下面的代码是一个带有自定义滑块的 React 组件,该滑块均匀地间隔 ISO 值,无论其数值如何。 shadcn/ui 用于创建滑块组件,它提供了更多自定义选项:

import React, { useState } from 'react';
import { Slider } from '@/components/ui/slider';
import { Label } from '@/components/ui/label';

const ISOSlider = () => {
  // ISO values array
  const isoValues = [3, 7, 12, 25, 50, 100, 200, 400, 800, 1600, 3200];
  
  // Instead of using actual ISO values, we'll use array indices
  const [selectedIndex, setSelectedIndex] = useState(isoValues.indexOf(100));

  // Convert index back to ISO value
  const currentISOValue = isoValues[selectedIndex];

  const handleSliderChange = (newValue) => {
    setSelectedIndex(newValue[0]);
  };

  return (
    <div className="w-full max-w-md space-y-4">
      <div className="flex items-center justify-between">
        <Label htmlFor="iso-slider" className="text-sm font-medium">
          ISO
        </Label>
        <span className="text-sm font-medium">
          {currentISOValue}
        </span>
      </div>
      
      <Slider
        id="iso-slider"
        min={0}
        max={isoValues.length - 1}
        step={1}
        value={[selectedIndex]}
        onValueChange={handleSliderChange}
        className="w-full"
      />
      
      <div className="flex justify-between text-xs text-gray-500">
        {isoValues.map((value, index) => (
          <span
            key={value}
            className="relative"
            style={{
              position: 'absolute',
              left: `${(index / (isoValues.length - 1)) * 100}%`,
              transform: 'translateX(-50%)'
            }}
          >
            {value}
          </span>
        ))}
      </div>
    </div>
  );
};

export default ISOSlider;

工作原理:

  • 我们不使用滑块的实际 ISO 值,而是使用数组索引(0 到 10)
  • 每个索引映射到数组中的一个 ISO 值
  • 无论实际 ISO 值如何,标记都是等间隔放置的
  • 我们通过将所选索引映射回 ISO 数组来维护状态中的实际 ISO 值

与原始代码的主要区别:

  • 我们使用索引(0 到 10)作为滑块值,而不是实际的 ISO 编号
  • 滑块步长为 1(在数组索引之间移动)
  • 我们将所选索引映射回来以获得实际的 ISO 值
  • 标记单独渲染在滑块下方,以便更好地控制间距

此方法可确保:

  • 所有 ISO 值沿滑块均匀分布
  • 滑块在值之间离散移动
  • 始终正确显示实际 ISO 值

您可以将样式或位置修改为您想要的外观。

我希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.