【问题标题】:Animate SVG line between custom input price range自定义输入价格范围之间的动画 SVG 线
【发布时间】:2021-04-16 13:43:42
【问题描述】:

我正在构建一个价格范围滑块,其中包含从最低价格到最高价格的 2 个输入和一条 SVG 线,该线将在滑块拇指内向左/向右动画。

我正在努力寻找该功能的数学方程式,因为如果有意义的话,左 SVG x1 值需要为 0 而不是最小输入值。

我留下了一个codeSandBox,所以你们可以看看我在这里想要实现的确切目标。

https://codesandbox.io/s/practical-bush-qq7dl?file=/src/App.js

import React, { useState } from "react";

export default function App() {
  const [minRange, setMinRange] = useState("");
  const [maxRange, setMaxRange] = useState("");
  const [staticRange, setStaticRange] = useState({
    min: 20,
    max: 112
  });
  const rangeSplit = staticRange.min + staticRange.max / 2;

  const handleChange = (input, e) => {
    const value = e.target.value;
    input === "min" ? setMinRange(value) : setMaxRange(value);
  };

  return (
    <div className="slider">
      <div className="slider__inputs">
        <input
          min={staticRange.min}
          max={rangeSplit}
          type="range"
          value={minRange}
          onChange={(e) => handleChange("min", e)}
        />
        <input
          min={rangeSplit}
          max={staticRange.max}
          type="range"
          value={maxRange}
          onChange={(e) => handleChange("max", e)}
        />

        <svg width="100%" height="4">
          <line
            x1={minRange}
            y1="0"
            x2={maxRange}
            y2="0"
            stroke="#444"
            stroke-width="12"
          ></line>
        </svg>
      </div>
      <div className="slider__range">
        <span>{`£${minRange}`}</span>
        <span>{`£${maxRange}`}</span>
      </div>
    </div>
  );
}

想要的效果:

【问题讨论】:

    标签: html css reactjs svg


    【解决方案1】:

    您的 svg 线是用 % 定义的,因此您需要将 x1、x2 值转换为上述 kca 所示的百分比。

    因此,您需要做的就是将总范围计算为 staticRange.max - staticRange.min。

    const totalRange=(staticRange.max - staticRange.min);
    

    此外,您需要将范围拆分设置为静态最小值和最大值之间的位置,因此如果您的最小值为 20,最大值为 112,则范围拆分需要为 66,(66 比 46 多) 20 和 46 小于 112)。

    const rangeSplit = staticRange.min+(totalRange / 2);
    

    然后,在定义 x1 和 x2 点时,将滑块位置与 staticRange.min 值之间的差值转换为 %。

    x1={(100 * ((minRange-staticRange.min)/totalRange)) + "%"}
    
    x2={(100 * ((maxRange-staticRange.min)/totalRange)) + "%"}
    

    如您所见,当 minRange == staticRange.min 时,值为 0%,当 maxRange == staticRange.max 时,值为 totalRange/totalRange,等于 100%。

    【讨论】:

    • 珍惜你的时间,工作就像一个魅力。
    【解决方案2】:

    数学是

    x% = 100% * 值/范围

    您必须对行的开头和结尾都进行此计算。

    说明

    Cross-multiplication

    x% / value = 100% / (112-20),乘以value 表示x% = 100% / (112-20) * value

    有时在除法之前先乘以更好,因此我喜欢总是这样做:
    x% = 100% * value / (112-20)

    示例

    const usePercent = (min, max, value)=>{
      const [ valuePct, setValuePct ] = useState(0);
    
      useEffect(()=>{
        const valueNum      = (value && value > min) ? value : min; // should never be less than min
        const rangeSize     = max - min;       // e.g. 112 - 20 = 92
        const relativeValue = valueNum - min;  // e.g. change value 20...112 --> 0...91
        const percent       = 100 * relativeValue / rangeSize  // 100% / 92 === x% / relativeValue
    
        setValuePct( percent );
    
      }, [ min, max, value ]);
    
      return valuePct;
    };
    
    const Line = (props)=>{
      const { minValue, maxValue, minOffset, maxOffset } = props;
      const minPercent = usePercent( minOffset, maxOffset, minValue );
      const maxPercent = usePercent( minOffset, maxOffset, maxValue );
    
      return (<svg width="100%" height="40">
        <line
            x1={ minPercent + '%' }
            y1="0"
            x2={ maxPercent + '%' }
            y2="0"
            stroke="#444"
            strokeWidth="12"
        />
      </svg>);
    };
    
    export default function App() {
    ...
      return (
    ...
            <Line
                minValue={ minRange }
                maxValue={ maxRange }
                minOffset={ 20 }
                maxOffset={ 112 }
            />
    ...
      );
    };
    

    【讨论】:

    • 感谢您花时间回答,我错过了那部分,我想我不擅长数学:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2021-04-10
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多