按住按钮时非线性增加值(React)

D00*_*ood 4 javascript user-experience reactjs

如果之前有人问过这个问题,我很抱歉,但我还没有找到任何可以帮助我的东西,而且我是 React 新手!

n我想要一个值随着用户按住按钮的每秒数而增加。现在它只是每 35 毫秒线性增加一次!

到目前为止我有这样的事情:

function Increaser() {

  const [value, setValue] = useState(0);
  const changeTimer: React.MutableRefObject<any> = useRef(null);

  function timeoutClearUp() {
    clearInterval(changeTimer.current);
  }

  function increment() {
    changeTimer.current = setInterval(() => setValue(prev => prev + 1), 35);
  };

  function onChange(e: any) {
    setValue(parseInt(e.target.value));
  }

  return (
    <div>
      <button onMouseUp={timeoutClearUp} onMouseDown={increment}>INCREASE</button>
      <input
            type="number"
            value={value}
            onChange={(e) => {onChange(e)}}
          />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

我尝试过添加另一个ref,但似乎不起作用!我可以在这段代码中添加一个小东西,以确保每秒value都会增加一个越来越大的值(用户按住按钮的时间越长)。

非常感谢!

  • 反应:^17.0.2
  • 打字稿:^4.5.5

小智 5

因为没有人给你真正的解决方案,所以这是一种做你想做的事情的方法。
我在这里所做的是使用对输入的引用,并在他们停止单击增量按钮或手动更改输入时更新状态中的值。
在增量函数中,我使用 setTimeout 创建自定义间隔,并且该间隔使用数学方程来确定下一个超时/间隔是什么。我使用的方程将在 41 秒内从 35 毫秒(开始)到 10 毫秒(结束),并且不会低于 10 毫秒。
这是我在本示例中用于加快间隔的时间图表。(x轴是以秒为单位的时间,y轴是以毫秒为单位的延迟) 我使用的时间函数图。

import { useState, useRef } from 'react';

function Increaser() {

    const [value, setValue] = useState(0);
    const myInputRef = useRef<HTMLInputElement>(null);
    let myTimeout: ReturnType<typeof setTimeout>;
    let startTime: Date;

    function stopInterval() {
        clearTimeout(myTimeout!);//Stop the interval in essence
        setValue(parseInt(myInputRef.current!.value!)||0) //Set the value of the input (in the mean time value is "floating")
    }
  
    function increment() {
      startTime = new Date();//Initialize when we started increasing the button
      myTimeout = setTimeout(function runIncrement() {//Start the timeout which is really a controlled interval
        const val = (parseInt(myInputRef!.current!.value)||0)+1;//Increment the value of the ref's target
        myInputRef!.current!.value = (val).toString()//Assign that incremented value to the ref
        const now = new Date();
        const delta = now.getTime() - startTime.getTime();
        const n = 10 + (1/(Math.pow(1.1,delta/1000-(2*Math.log(5))/Math.log(1.1))));//Whatever
        //The math function I have chosen above will go from 35 ms to 10 ms in 41 seconds.
        //The function will not go lower than 10 ms and starts at 35 ms
        //However you can use whatever function or math you want to get it to do as you wish.
        //...
        //whatever logic here you want to calculate when we will trigger the increment again.
        //...
        myTimeout = setTimeout(runIncrement, parseInt(n.toString()));//Increment again after the variable n milliseconds which we calculate above
      },35);//Start the interval with an initial time of 35 milliseconds
      //Now we know when the interval started, and we can
    };
  
    function onChange(e: any) {
      setValue(parseInt(e.target.value));
    }
  
    return (
      <div>
        <button onMouseUp={stopInterval} onMouseDown={increment}>INCREASE</button>
        <input
              type="number"
              onChange={(e) => {onChange(e)}}
              ref={myInputRef}
            />
      </div>
    );
  }
export default Increaser;
Run Code Online (Sandbox Code Playgroud)

`

我对 SO 在这里所做的轻微格式化表示歉意(与我的 VS 代码编辑器结合使用)。