所以,我正在尝试用 HTML 和 JavaScript 制作一个随机数生成器。我希望它有一个东西,在它达到随机数之前它会增加一个,所以它有某种“动画”,但我不能让它工作。这是我的代码:
document.getElementById("numbergenerator").onclick = generateNumber;
function generateNumber() {
numbervalue = Math.floor(Math.random() * 1001);
for(var i = 0; i < numbervalue; i++) {
setTimeout(goUpThing(i), 10);
}
document.getElementById("numberdisplay").innerHTML = numbervalue;
}
function goUpThing(number) {
document.getElementById("numberdisplay").innerHTML = number;
}
<html>
<body>
<h1>
<em>random stuff</em>
</h1>
<hr>
<h2 id="numberdisplay">
there is no number yet
</h2>
<div>
<button id="numbergenerator" type="button">
generate a random number
</button>
</div>
</body>
</html>
有人可以帮帮我吗?顺便说一句,我正在使用 JSFiddle 来运行我的代码。
您可以使用
setInterval()
和clearInterval()
。
setInterval
允许函数以 ms
中设置的时间间隔运行(本例中为 1)。
它被分配给一个名为interval
的变量以供以后参考。
内部函数在每个时间间隔递增 counter
,直到满足条件 - counter
等于随机 numbervalue
。然后将先前的变量interval
传递给clearInterval
并停止运行内部函数
document.getElementById("numbergenerator").onclick = generateNumber;
function generateNumber() {
let numbervalue = Math.floor(Math.random() * 1001);
let counter = 0;
let interval = setInterval(() => {
document.getElementById("numberdisplay").innerHTML = counter;
counter++;
if (counter === numbervalue) {
clearInterval(interval);
}
}, 1);
}
<body>
<h1>
<em>random stuff</em>
</h1>
<hr>
<h2 id="numberdisplay">
there is no number yet
</h2>
<div>
<button id="numbergenerator" type="button">
generate a random number
</button>
</div>
</body>
有几种方法可以实现这一点。
async/await
与setTimeout
或requestAnimationFrame
组合来等待显示下一个数字。 (示例 1 和 2)requestAnimationFrame()
循环。 (例 5)setTimeout
或 requestAnimationFrame
生成承诺链以等待显示下一个数字。 (例 6)可能还有更多。
所有示例都显示一个从 1-1000 的随机数。
示例的执行时间可能会有所不同。如果每个数字必须至少显示一次,则应使用
requestAnimationFrame()
。它可能比 10 毫秒的间隔或超时“慢”,因为它基本上取决于屏幕的刷新率。在 60hz 上,它类似于 17ms 的间隔(1000 / 60 = 16.666~),而 setTimeout 或 setInterval 回调可能会在同一帧多次调用。
示例 3-6 也适用于旧版浏览器不支持异步/等待,如果需要,您可能还需要将箭头功能更改为经典功能。如果不支持Promise,示例 6 可能还需要一个 Promise polyfill。
生成一个从1到1000的随机数,在循环内等待超时结束,然后脚本继续。
// example 1 using async/await w/ setTimeout on a promise callback
button.onclick = async () => {
button.disabled = true;
let rand = Math.ceil(Math.random() * 1000);
for (let i = 1; i <= rand; i++) {
output.innerText = i;
/**
* You could also define a sleep function and await it
* function sleep(t) { return new Promise(r => setTimeout(r,t); }
*
* await sleep(10);
*/
await new Promise(resolve => setTimeout(resolve, 10));
}
button.disabled = false;
}
<h4>Example 1: async function w/ await setTimeout</h4>
<p id="output">click the button</p>
<button id="button" type="button">launch</button>
类似于#1,它只是等待下一帧。
// example 2 using async/await w/ requestAnimationFrame on a promise
// this example will decrease the speed hardly,
// if you switch to another tab while it's counting up
button.onclick = async () => {
button.disabled = true;
let rand = Math.ceil(Math.random() * 1000);
for (let i = 1; i <= rand; i++) {
output.innerText = i;
await new Promise(resolve => requestAnimationFrame(resolve));
}
button.disabled = false;
}
<h4>Example 2: async function w/ await requestAnimationFrame</h4>
<p id="output">click the button</p>
<button id="button" type="button">launch</button>
一次启动多个超时,每个超时延迟
10 * numberToDisplay
ms。
// example 3 starting N setTimeout calls at once
button.onclick = () => {
button.disabled = true;
let rand = Math.ceil(Math.random() * 1000);
for (let i = 1; i <= rand; i++) {
setTimeout((value) => {
output.innerText = value;
// pass current value of i to the function in the setTimeout call
}, i * 10, i);
}
setTimeout(() => {
button.disabled = false;
}, 10 * rand + 10)
}
<h4>Example 3: starting N setTimeout requests at the same time</h4>
<p id="output">click the button</p>
<button id="button" type="button">launch</button>
使用带有结束条件的 setInterval。
// example 4 setInterval with end condition
button.onclick = () => {
button.disabled = true;
const rand = Math.ceil(Math.random() * 1000);
const interval = setInterval((obj) => {
output.innerText = ++obj.v;
if (obj.v == rand) {
clearInterval(interval);
button.disabled = false;
}
// passing an object, to keep the reference for increment,
// you could also define the counter outside the function
// using let or var and increase it's value on every tick
}, 10, { v: 0 })
}
<h4>Example 4: setInterval with end condition</h4>
<p id="output">click the button</p>
<button id="button" type="button">launch</button>
类似于#4,但是这个使用带有结束条件的requestAnimationFrame,每次调用函数时都会增加传递的值,从0开始,显示的第一个数字是1。
// example 5: requestAnimationFrame-loop with end condition
// like example 2, this will decrease the speed hardly,
// if you switch to another tab while it's running
button.onclick = () => {
button.disabled = true;
const rand = Math.ceil(Math.random() * 1000);
(function count(i) {
output.innerText = ++i;
if (i == rand) {
button.disabled = false;
} else {
requestAnimationFrame(() => count(i));
}
})(0) // invoke the function directly to start
}
<h4>Example 5: requestAnimationFrame-loop with end condition</h4>
<p id="output">click the button</p>
<button id="button" type="button">launch</button>
这与 #1 和 #2 的工作方式类似,并确保仅在承诺履行后才显示下一个数字。
// example 6: Promise-Chain
button.onclick = () => {
button.disabled = true;
let rand = Math.ceil(Math.random() * 1000);
let prom = Promise.resolve(0);
while (rand--) {
prom = prom.then(v => {
output.innerText = ++v;
return new Promise(res => setTimeout(res, 10, v))
});
}
prom.finally(() => {
button.disabled = false;
});
}
buttonRAF.onclick = () => {
buttonRAF.disabled = true;
let rand = Math.ceil(Math.random() * 1000);
let prom = Promise.resolve(0);
while (rand--) {
prom = prom.then(v => {
outputRAF.innerText = ++v;
return new Promise(res => requestAnimationFrame(() => res(v)))
});
}
prom.finally(() => {
buttonRAF.disabled = false;
});
}
<h4>
Example 6: Promise-Chain
<button onclick="button.click(), buttonRAF.click()">both</button>
</h4>
<p id="output">click the button</p>
<button id="button">launch (setTimeout)</button>
<p id="outputRAF">click the button</p>
<button id="buttonRAF">launch (requestAnimationFrame)</button>