为什么使用 setInterval 在 HTML 和 JavaScript 中落下方框没有按预期工作?
Why falling box in HTML & JavaScript using setInterval doesn't work as expected?
https://codepen.io/skinaqua123/pen/WNZZgEy
<div id="container">
<div id="box"></div>
</div>
#container {
background-color: black;
width: 800px;
height: 500px;
position: relative;
}
#box {
width: 50px;
height: 50px;
background-color: yellow;
position: absolute;
top: 0px;
transition: top 0.5s ease-out 0s;
}
html {
height: 100%;
max-height: 100%;
}
const box = document.querySelector("#box");
console.log(box.offsetTop);
const fallingMovement = setInterval(() => {
box.style.top = box.offsetTop + 50 + "px";
if (box.offsetTop >= 500 - 50 - 50) {
clearInterval(fallingMovement);
}
}, 1000);
嗨,我正在为我的 html 游戏测试一些代码。我想要一个盒子掉下来但不要超出包装 div.
我的包裹高度div(容器)是500px,我的盒子是50px。我认为它应该在顶部为 450px (500-50) 时停止。
但实际上,它仍然比应有的多了 50 像素。当我将它更改为 400 时,它工作正常。
为什么会这样?即使我调用了 clearInterval
,我给 setInterval
的函数是否会再次执行?
谢谢
您必须在调用 clearInterval
后更改 box.style.top
const box = document.querySelector("#box");
const fallingMovement = setInterval(() => {
console.log('run interval --------')
console.log('current offsetTop', box.offsetTop)
console.log('future offsetTop', box.offsetTop + 50)
if (box.offsetTop >= 500 - 50) {
clearInterval(fallingMovement);
return;
}
box.style.top = box.offsetTop + 50 + "px";
}, 1000);
间隔回调执行和渲染结果之间存在时间延迟。您可以通过比较 box.offsetTop
在更改 box.style.top
后立即和超时后的结果来看到这一点:
const fallingMovement = setInterval(() => {
box.style.top = box.offsetTop + 50 + "px";
if (box.offsetTop >= 500 - 50 - 50) {
clearInterval(fallingMovement);
console.log(box.offsetTop); // Will print 400.
setTimeout(() => {console.log(box.offsetTop);}, 500); // Will print 450.
}
}, 1000);
要解决此问题,您只需在更新之前执行检查,而不是更新之后:
const fallingMovement = setInterval(() => {
if (box.offsetTop >= 500 - 50 - 50) {
clearInterval(fallingMovement);
return;
}
box.style.top = box.offsetTop + 50 + "px";
}, 1000);
或者,您可以考虑这个延迟的偏移量更新:
const fallingMovement = setInterval(() => {
box.style.top = box.offsetTop + 50 + "px";
if (box.offsetTop + 50 >= 500 - 50 -50) {
clearInterval(fallingMovement);
}
}, 1000);
其实是个很简单但是容易没意识到的问题
您的测试发生在移动调用之后。您首先调用移动,然后再测试它是否应该移动。
您可以通过稍微改变您的逻辑来修复它。首先你检查它是否应该移动,然后你调用移动。例如:
const fallingMovement = setInterval(() => {
if (box.offsetTop < 500 - 50) {
box.style.top = box.offsetTop + 50 + "px";
} else {
clearInterval(fallingMovement);
}
}, 1000);
所以,首先我要检查盒子顶部和包装器顶部的距离是否小于 450,然后我会移动。如果大于等于450,则清空区间,不调用运动。这样,它将按预期工作。
https://codepen.io/skinaqua123/pen/WNZZgEy
<div id="container">
<div id="box"></div>
</div>
#container {
background-color: black;
width: 800px;
height: 500px;
position: relative;
}
#box {
width: 50px;
height: 50px;
background-color: yellow;
position: absolute;
top: 0px;
transition: top 0.5s ease-out 0s;
}
html {
height: 100%;
max-height: 100%;
}
const box = document.querySelector("#box");
console.log(box.offsetTop);
const fallingMovement = setInterval(() => {
box.style.top = box.offsetTop + 50 + "px";
if (box.offsetTop >= 500 - 50 - 50) {
clearInterval(fallingMovement);
}
}, 1000);
嗨,我正在为我的 html 游戏测试一些代码。我想要一个盒子掉下来但不要超出包装 div.
我的包裹高度div(容器)是500px,我的盒子是50px。我认为它应该在顶部为 450px (500-50) 时停止。
但实际上,它仍然比应有的多了 50 像素。当我将它更改为 400 时,它工作正常。
为什么会这样?即使我调用了 clearInterval
,我给 setInterval
的函数是否会再次执行?
谢谢
您必须在调用 clearInterval
box.style.top
const box = document.querySelector("#box");
const fallingMovement = setInterval(() => {
console.log('run interval --------')
console.log('current offsetTop', box.offsetTop)
console.log('future offsetTop', box.offsetTop + 50)
if (box.offsetTop >= 500 - 50) {
clearInterval(fallingMovement);
return;
}
box.style.top = box.offsetTop + 50 + "px";
}, 1000);
间隔回调执行和渲染结果之间存在时间延迟。您可以通过比较 box.offsetTop
在更改 box.style.top
后立即和超时后的结果来看到这一点:
const fallingMovement = setInterval(() => {
box.style.top = box.offsetTop + 50 + "px";
if (box.offsetTop >= 500 - 50 - 50) {
clearInterval(fallingMovement);
console.log(box.offsetTop); // Will print 400.
setTimeout(() => {console.log(box.offsetTop);}, 500); // Will print 450.
}
}, 1000);
要解决此问题,您只需在更新之前执行检查,而不是更新之后:
const fallingMovement = setInterval(() => {
if (box.offsetTop >= 500 - 50 - 50) {
clearInterval(fallingMovement);
return;
}
box.style.top = box.offsetTop + 50 + "px";
}, 1000);
或者,您可以考虑这个延迟的偏移量更新:
const fallingMovement = setInterval(() => {
box.style.top = box.offsetTop + 50 + "px";
if (box.offsetTop + 50 >= 500 - 50 -50) {
clearInterval(fallingMovement);
}
}, 1000);
其实是个很简单但是容易没意识到的问题
您的测试发生在移动调用之后。您首先调用移动,然后再测试它是否应该移动。
您可以通过稍微改变您的逻辑来修复它。首先你检查它是否应该移动,然后你调用移动。例如:
const fallingMovement = setInterval(() => {
if (box.offsetTop < 500 - 50) {
box.style.top = box.offsetTop + 50 + "px";
} else {
clearInterval(fallingMovement);
}
}, 1000);
所以,首先我要检查盒子顶部和包装器顶部的距离是否小于 450,然后我会移动。如果大于等于450,则清空区间,不调用运动。这样,它将按预期工作。