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

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

Inversing slider value without affecting drag functionality MUI Slider React

问题

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

  1. const handleSelectionChange = (e: any) => {
  2. if (typeof e.target.value === 'string') {
  3. onChange(e.target.value)
  4. } else {
  5. onChange(Number(e.target.value))
  6. }
  7. }
  8. <Slider
  9. aria-label='DiceRoll'
  10. defaultValue={50}
  11. valueLabelDisplay='auto'
  12. step={1}
  13. min={0}
  14. max={100}
  15. value={overUnder ? 100 - targetNumber : targetNumber} // overUnder 是布尔值targetNumber 的范围是从 0 100
  16. marks={marks}
  17. onChange={handleSelectionChange}
  18. />

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

英文:

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.

  1. const handleSelectionChange = (e: any) =&gt; {
  2. if (typeof e.target.value === &#39;string&#39;) {
  3. onChange(e.target.value)
  4. } else {
  5. onChange(Number(e.target.value))
  6. }
  7. }
  8. &lt;Slider
  9. aria-label=&#39;DiceRoll&#39;
  10. defaultValue={50}
  11. valueLabelDisplay=&#39;auto&#39;
  12. step={1}
  13. min={0}
  14. max={100}
  15. value={overUnder ? 100 - targetNumber : targetNumber} //overUnder is boolean and targetNumber ranges from 0 to 100.
  16. marks={marks}
  17. onChange={handleSelectionChange}
  18. /&gt;

答案1

得分: 0

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

请使用以下代码:

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

将值恢复为正常:

  1. value={targetNumber}

以下是代码示例:

  1. const { StrictMode, useState } = React;
  2. const { createRoot } = ReactDOM;
  3. const App = () => {
  4. const [overUnder, setOverUnder] = useState(false);
  5. const [targetNumber, setTargetNumber] = useState(42.0);
  6. const handleSelectionChange = (e) => {
  7. if (typeof e.target.value === "string") {
  8. setTargetNumber(e.target.value);
  9. } else {
  10. setTargetNumber(Number(e.target.value));
  11. }
  12. };
  13. const onFlip = () => {
  14. setOverUnder((s) => !s);
  15. };
  16. return (
  17. <div>
  18. <div>
  19. <button onClick={onFlip}>Flip</button>
  20. </div>
  21. <div>Target Number: {targetNumber}</div>
  22. <div>Over Under: {`${overUnder}`}</div>
  23. <MaterialUI.Slider
  24. aria-label="DiceRoll"
  25. defaultValue={50}
  26. valueLabelDisplay="on"
  27. step={1}
  28. min={0}
  29. max={100}
  30. value={targetNumber}
  31. valueLabelFormat={(v) => (overUnder ? 100 - v : v)}
  32. marks={false}
  33. inverted={true}
  34. onChange={handleSelectionChange}
  35. sx={{ pt: "10rem" }}
  36. />
  37. </div>
  38. );
  39. }
  40. const rootElement = document.getElementById("root");
  41. const root = createRoot(rootElement);
  42. root.render(
  43. <StrictMode>
  44. <App />
  45. </StrictMode>
  46. );

希望这对您有所帮助。

英文:

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 -->

  1. const { StrictMode, useState } = React;
  2. const { createRoot } = ReactDOM;
  3. const App = () =&gt; {
  4. const [overUnder, setOverUnder] = useState(false);
  5. const [targetNumber, setTargetNumber] = useState(42.0);
  6. const handleSelectionChange = (e) =&gt; {
  7. if (typeof e.target.value === &quot;string&quot;) {
  8. setTargetNumber(e.target.value);
  9. } else {
  10. setTargetNumber(Number(e.target.value));
  11. }
  12. };
  13. const onFlip = () =&gt; {
  14. setOverUnder((s) =&gt; !s);
  15. };
  16. return (
  17. &lt;div&gt;
  18. &lt;div&gt;
  19. &lt;button onClick={onFlip}&gt;Flip&lt;/button&gt;
  20. &lt;/div&gt;
  21. &lt;div&gt;Target Number: {targetNumber}&lt;/div&gt;
  22. &lt;div&gt;Over Under: {`${overUnder}`}&lt;/div&gt;
  23. &lt;MaterialUI.Slider
  24. aria-label=&quot;DiceRoll&quot;
  25. defaultValue={50}
  26. valueLabelDisplay=&quot;on&quot;
  27. step={1}
  28. min={0}
  29. max={100}
  30. value={targetNumber}
  31. valueLabelFormat={(v) =&gt; (overUnder ? 100 - v : v)}
  32. marks={false}
  33. inverted={true}
  34. onChange={handleSelectionChange}
  35. sx={{ pt: &quot;10rem&quot; }}
  36. /&gt;
  37. &lt;/div&gt;
  38. );
  39. }
  40. const rootElement = document.getElementById(&quot;root&quot;);
  41. const root = createRoot(rootElement);
  42. root.render(
  43. &lt;StrictMode&gt;
  44. &lt;App /&gt;
  45. &lt;/StrictMode&gt;
  46. );

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

  1. &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
  2. &lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
  3. &lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
  4. &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行代码。我们只需引入另一个状态,其唯一目的是显示正确的滑块值。

  1. const handleSelectionChange = (e: any) => {
  2. if (overUnder) { // overUnder的默认值为true
  3. if (typeof e.target.value === 'string') {
  4. onChange(e.target.value);
  5. } else {
  6. onChange(Number(e.target.value));
  7. }
  8. } else {
  9. if (typeof e.target.value === 'string') {
  10. onChange(100 - e.target.value);
  11. setFlippedTargetNumber(e.target.value);
  12. } else {
  13. onChange(100 - Number(e.target.value));
  14. setFlippedTargetNumber(Number(e.target.value));
  15. }
  16. }
  17. }
  18. const [flippedTargetNumber, setFlippedTargetNumber] = useState<number>(50);
  19. <Slider
  20. aria-label='DiceRoll'
  21. defaultValue={50}
  22. valueLabelDisplay='auto'
  23. step={1}
  24. min={0}
  25. max={100}
  26. value={overUnder ? targetNumber : flippedTargetNumber} // overUnder是布尔值,targetNumber范围从0到100。
  27. marks={marks}
  28. onChange={handleSelectionChange}
  29. />

基本上,这是它的作用:当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.

  1. const handleSelectionChange = (e: any) =&gt; {
  2. if(overUnder){ //defaultValue of overUnder is true
  3. if (typeof e.target.value === &#39;string&#39;) {
  4. onChange(e.target.value)
  5. } else {
  6. onChange(Number(e.target.value))
  7. }
  8. } else {
  9. if (typeof e.target.value === &#39;string&#39;) {
  10. onChange(100 - e.target.value)
  11. setFlippedTargetNumber(e.target.value)
  12. } else {
  13. onChange(100 - Number(e.target.value))
  14. setFlippedTargetNumber(Number(e.target.value))
  15. }
  16. }
  17. }
  18. const [ flippedTargetNumber, setFlippedTargetNumber] = useState&lt;number&gt;(50)
  19. &lt;Slider
  20. aria-label=&#39;DiceRoll&#39;
  21. defaultValue={50}
  22. valueLabelDisplay=&#39;auto&#39;
  23. step={1}
  24. min={0}
  25. max={100}
  26. value={overUnder ? targetNumber : flippedTargetNumber} //overUnder is boolean and targetNumber ranges from 0 to 100.
  27. marks={marks}
  28. onChange={handleSelectionChange}
  29. /&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:

确定