按住按钮时非线性增加值(反应)
Increasing a value non-linearly when holding down a button (React)
如果之前有人问过这个问题,我深表歉意,但我还没有找到任何可以帮助我的东西,而且我是 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>
);
}
我试过添加另一个 ref
但似乎没有用!我可以向此代码添加什么小东西,以确保每秒 value
递增一个越来越大的值(用户按住按钮的时间越长)。
非常感谢!
- 反应:^17.0.2
- 打字稿:^4.5.5
想要每秒都在成长,就应该改变
...
changeTimer.current = setInterval(() => setValue(prev => prev + 1), 35);
...
<input
type="number"
value={value}
/>
到
...
changeTimer.current = setInterval(() => setValue(prev => prev + 35), 35);
...
<input
type="number"
value={value/1000}
/>
因为setInterval
的第二个参数是毫秒
完整代码和演示:
import React, { useState, useRef } from "react";
export default function Increaser() {
const [value, setValue] = useState(0);
const changeTimer = useRef(null);
function timeoutClearUp() {
if (changeTimer.current) {
clearInterval(changeTimer.current);
changeTimer.current = null;
}
}
function increment() {
changeTimer.current = setInterval(() => {
setValue((prev) => prev + 35);
}, 35);
}
return (
<div>
<button onMouseUp={timeoutClearUp} onMouseDown={increment}>
INCREASE
</button>
<button
onClick={() => {
setValue(0);
}}
>
Reset
</button>
<div>{value / 1000}</div>
</div>
);
}
因为没有人给你一个真正的解决方案,这里有一种方法可以做你想做的事。
我在这里所做的是使用对输入的引用,并在他们停止单击增量按钮或手动更改输入时更新您状态中的值。
在增量函数中,我使用 setTimeout 创建自定义间隔,该间隔使用数学方程式来确定下一个 timeout/interval 是什么。我使用的等式将在 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;
`
对于 S.O 的轻微格式表示歉意。在这里做(结合我的 VS 代码编辑器)。
感谢 SharpInnovativeTechnologies 的回答,我意识到自己是多么愚蠢,并找到了一个简单的解决方案:
function increment() {
const past = Date.now()
const rate = 500;
changeTimer.current = setInterval(() => {
const diff = Math.floor((Date.now() - past) / rate);
setValue(prev => prev + (1 + diff))
}, 50);
}
其中 rate
是一种灵敏度调整。
因此,每 50 毫秒,Date.now() - past
会随着 setter 增加并提升 value
。
如果之前有人问过这个问题,我深表歉意,但我还没有找到任何可以帮助我的东西,而且我是 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>
);
}
我试过添加另一个 ref
但似乎没有用!我可以向此代码添加什么小东西,以确保每秒 value
递增一个越来越大的值(用户按住按钮的时间越长)。
非常感谢!
- 反应:^17.0.2
- 打字稿:^4.5.5
想要每秒都在成长,就应该改变
...
changeTimer.current = setInterval(() => setValue(prev => prev + 1), 35);
...
<input
type="number"
value={value}
/>
到
...
changeTimer.current = setInterval(() => setValue(prev => prev + 35), 35);
...
<input
type="number"
value={value/1000}
/>
因为setInterval
的第二个参数是毫秒
完整代码和演示:
import React, { useState, useRef } from "react";
export default function Increaser() {
const [value, setValue] = useState(0);
const changeTimer = useRef(null);
function timeoutClearUp() {
if (changeTimer.current) {
clearInterval(changeTimer.current);
changeTimer.current = null;
}
}
function increment() {
changeTimer.current = setInterval(() => {
setValue((prev) => prev + 35);
}, 35);
}
return (
<div>
<button onMouseUp={timeoutClearUp} onMouseDown={increment}>
INCREASE
</button>
<button
onClick={() => {
setValue(0);
}}
>
Reset
</button>
<div>{value / 1000}</div>
</div>
);
}
因为没有人给你一个真正的解决方案,这里有一种方法可以做你想做的事。
我在这里所做的是使用对输入的引用,并在他们停止单击增量按钮或手动更改输入时更新您状态中的值。
在增量函数中,我使用 setTimeout 创建自定义间隔,该间隔使用数学方程式来确定下一个 timeout/interval 是什么。我使用的等式将在 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;
`
对于 S.O 的轻微格式表示歉意。在这里做(结合我的 VS 代码编辑器)。
感谢 SharpInnovativeTechnologies 的回答,我意识到自己是多么愚蠢,并找到了一个简单的解决方案:
function increment() {
const past = Date.now()
const rate = 500;
changeTimer.current = setInterval(() => {
const diff = Math.floor((Date.now() - past) / rate);
setValue(prev => prev + (1 + diff))
}, 50);
}
其中 rate
是一种灵敏度调整。
因此,每 50 毫秒,Date.now() - past
会随着 setter 增加并提升 value
。