反转滑块值而不影响拖动功能 MUI Slider React

huangapple go评论67阅读模式
英文:

Inversing slider value without affecting drag functionality MUI Slider React

问题

我有一个 MUI 滑块,滑块的值需要根据布尔变量进行反转。我的当前代码能够正确反转它,但它也反转了拖动功能,也就是说,如果我试图将滑块向 0 拖动,它会移向 100。我无法想出一个解决办法来修复这个问题。如果有人有任何建议,我会很感激。

const handleSelectionChange = (e: any) => {
  if (typeof e.target.value === 'string') {
    onChange(e.target.value)
  } else {
    onChange(Number(e.target.value))
  }
}

<Slider
    aria-label='DiceRoll'
    defaultValue={50}
    valueLabelDisplay='auto'
    step={1}
    min={0}
    max={100}
    value={overUnder ? 100 - targetNumber : targetNumber} // overUnder 是布尔值targetNumber 的范围是从 0  100
    marks={marks}
    onChange={handleSelectionChange}
/>

以上是您提供的代码的翻译部分。

英文:

I have a MUI slider where the value of the slider needs to be inverted based on a boolean variable. My current code inverts it correctly but it also inverts the drag functionality, meaning if I tried to drag my slider towards 0, it would move towards 100 instead. I can't think of a workaround to correct this. Would appreciate if anyone has any suggestions I could try.

const handleSelectionChange = (e: any) =&gt; {
  if (typeof e.target.value === &#39;string&#39;) {
    onChange(e.target.value)
  } else {
    onChange(Number(e.target.value))
  }
}
&lt;Slider
            aria-label=&#39;DiceRoll&#39;
            defaultValue={50}
            valueLabelDisplay=&#39;auto&#39;
            step={1}
            min={0}
            max={100}
            value={overUnder ? 100 - targetNumber : targetNumber} //overUnder is boolean and targetNumber ranges from 0 to 100.
            marks={marks}
            onChange={handleSelectionChange}
/&gt; 

答案1

得分: 0

使用valueLabelFormat函数,您可以简单地格式化数字显示而不是数字值本身,从而避免这个问题。

请使用以下代码:

valueLabelFormat={(v) => (overUnder ? 100 - v : v)}

将值恢复为正常:

value={targetNumber}

以下是代码示例:

const { StrictMode, useState } = React;
const { createRoot } = ReactDOM;

const App = () => {

  const [overUnder, setOverUnder] = useState(false);
  const [targetNumber, setTargetNumber] = useState(42.0);
  
  const handleSelectionChange = (e) => {
    if (typeof e.target.value === "string") {
      setTargetNumber(e.target.value);
    } else {
      setTargetNumber(Number(e.target.value));
    }
  };
  
  const onFlip = () => {
    setOverUnder((s) => !s);
  };
  
  return (
    <div>
      <div>
        <button onClick={onFlip}>Flip</button>
      </div>
      <div>Target Number: {targetNumber}</div>
      <div>Over Under: {`${overUnder}`}</div>
      <MaterialUI.Slider
        aria-label="DiceRoll"
        defaultValue={50}
        valueLabelDisplay="on"
        step={1}
        min={0}
        max={100}
        value={targetNumber}
        valueLabelFormat={(v) => (overUnder ? 100 - v : v)}
        marks={false}
        inverted={true}
        onChange={handleSelectionChange}
        sx={{ pt: "10rem" }}
      />
    </div>
  );
}

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

希望这对您有所帮助。

英文:

Using the valueLabelFormat function, you can simply format the number display instead of the number value itself, preventing the problem.

Use this instead:

valueLabelFormat={(v) =&gt; (overUnder ? 100 - v : v)}

Set the value back to normal:

value={targetNumber}

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const { StrictMode, useState } = React;
const { createRoot } = ReactDOM;
const App = () =&gt; {
const [overUnder, setOverUnder] = useState(false);
const [targetNumber, setTargetNumber] = useState(42.0);
const handleSelectionChange = (e) =&gt; {
if (typeof e.target.value === &quot;string&quot;) {
setTargetNumber(e.target.value);
} else {
setTargetNumber(Number(e.target.value));
}
};
const onFlip = () =&gt; {
setOverUnder((s) =&gt; !s);
};
return (
&lt;div&gt;
&lt;div&gt;
&lt;button onClick={onFlip}&gt;Flip&lt;/button&gt;
&lt;/div&gt;
&lt;div&gt;Target Number: {targetNumber}&lt;/div&gt;
&lt;div&gt;Over Under: {`${overUnder}`}&lt;/div&gt;
&lt;MaterialUI.Slider
aria-label=&quot;DiceRoll&quot;
defaultValue={50}
valueLabelDisplay=&quot;on&quot;
step={1}
min={0}
max={100}
value={targetNumber}
valueLabelFormat={(v) =&gt; (overUnder ? 100 - v : v)}
marks={false}
inverted={true}
onChange={handleSelectionChange}
sx={{ pt: &quot;10rem&quot; }}
/&gt;
&lt;/div&gt;
);
}
const rootElement = document.getElementById(&quot;root&quot;);
const root = createRoot(rootElement);
root.render(
&lt;StrictMode&gt;
&lt;App /&gt;
&lt;/StrictMode&gt;
);

<!-- language: lang-html -->

&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://unpkg.com/@mui/material@latest/umd/material-ui.production.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

Also a sandbox for reference.

答案2

得分: 0

在几个小时之后,我找到了解决方案,实际上这是一个相当简单的解决方案,只需要额外的3行代码。我们只需引入另一个状态,其唯一目的是显示正确的滑块值。

const handleSelectionChange = (e: any) => {
  if (overUnder) { // overUnder的默认值为true
    if (typeof e.target.value === 'string') {
      onChange(e.target.value);
    } else {
      onChange(Number(e.target.value));
    }
  } else {
    if (typeof e.target.value === 'string') {
      onChange(100 - e.target.value);
      setFlippedTargetNumber(e.target.value);
    } else {
      onChange(100 - Number(e.target.value));
      setFlippedTargetNumber(Number(e.target.value));
    }
  }
}

const [flippedTargetNumber, setFlippedTargetNumber] = useState<number>(50);

<Slider
  aria-label='DiceRoll'
  defaultValue={50}
  valueLabelDisplay='auto'
  step={1}
  min={0}
  max={100}
  value={overUnder ? targetNumber : flippedTargetNumber} // overUnder是布尔值,targetNumber范围从0到100。
  marks={marks}
  onChange={handleSelectionChange}
/>

基本上,这是它的作用:当overUndertrue时,滑块将正常工作。当它被翻转并且overUnderfalse时,onChange将更新targetNumber为其相反值(对于其他组件是必需的)。而setFlippedTargetNumber将用作滑块值,而不是targetNumber

希望这对于面临类似问题的任何人有所帮助。 反转滑块值而不影响拖动功能 MUI Slider React

英文:

So after a few hours I've found the solution, it's actually a pretty simple solution, just an additional 3 lines of codes. We just have to introduce another state which only purpose is to display the correct slider Value.

const handleSelectionChange = (e: any) =&gt; {
if(overUnder){ //defaultValue of overUnder is true
if (typeof e.target.value === &#39;string&#39;) {
onChange(e.target.value)
} else {
onChange(Number(e.target.value))
}
} else {
if (typeof e.target.value === &#39;string&#39;) {
onChange(100 - e.target.value)
setFlippedTargetNumber(e.target.value)
} else {
onChange(100 - Number(e.target.value))
setFlippedTargetNumber(Number(e.target.value))
}
}
}
const [ flippedTargetNumber, setFlippedTargetNumber] = useState&lt;number&gt;(50)
&lt;Slider
aria-label=&#39;DiceRoll&#39;
defaultValue={50}
valueLabelDisplay=&#39;auto&#39;
step={1}
min={0}
max={100}
value={overUnder ? targetNumber : flippedTargetNumber} //overUnder is boolean and targetNumber ranges from 0 to 100.
marks={marks}
onChange={handleSelectionChange}
/&gt; 

basically what this does is, when overUnder = true, and when it's true, the slider would just work normally. when it is flipped and overUnder = false, onChange will update targetNumber to inverse [which is needed for other components]. and setFlippedTargetNumber will be used as slider Value instead of targetNumber.

Hope this helps anyone who is facing a similar problem. 反转滑块值而不影响拖动功能 MUI Slider React

huangapple
  • 本文由 发表于 2023年2月19日 15:06:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75498518.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定