当我使用 onKeyDown 事件时移动元素被延迟
Moving elements is delayed when I'm using the onKeyDown event
我试图在按住某个键(在本例中为向左或向右箭头)时移动元素,但是当我按住某个键时,移动会延迟大约一秒钟。我使用了错误的事件还是我的代码有什么问题?
我正在使用 onKeyDown
事件来触发移动。
<head>
<script>
var objX = 100;
function blockMove(e){
if (e.keyCode == 37) { //move left
objX-=4;
document.getElementById("object").style.left = objX + "px";
} else if (e.keyCode == 39) { //move right
objX+=4;
document.getElementById("object").style.left = objX + "px";
}
}
</script>
</head>
<body onkeydown="blockMove(event)">
<div id=object style="height:10px;width:80px;background-color:red;position:absolute;top:50px;left:100px"></div>
</body>
请耐心等待,这有点长而且可能有问题:
(如果你想自己做的话也剧透一下)
<head>
<script>
var objX = 100;
var leftDown = false;
var rightDown = false;
function blockMove(e){
if(e.keyCode == 37 && !leftDown) { //move left
leftDown = true;
objX-=4;
document.getElementById("object").style.left = objX + "px";
}else if(e.keyCode == 39 && !rightDown) { //move right
rightDown = true;
objX+=4;
document.getElementById("object").style.left = objX + "px";
}}
function stopMove(e)
{
if( e.keyCode == 37 )
leftDown = false;
if( e.keyCode == 39 )
rightDown = false;
}
function timer()
{
if( leftDown )
objX -= 4;
if( rightDown )
objX += 4;
document.getElementById("object").style.left = objX + "px";
}
setInterval(timer, 100);
</script>
</head>
<body onkeydown="blockMove(event)" onkeyup="stopMove(event)">
<div id=object
style="height:10px;width:80px;background-color:red;position:absolute;top:360px;left:100px"
></div>
</body>
而不是依赖于用户键盘重复率,这是最终导致多次调用 blockMove
的原因,您应该使用计时器来检查对象是否应该以一致的速率移动(每个在我下面的例子中是 20ms)。这意味着无论用户的重复率设置如何,这对所有用户来说都是一致的体验。
然后您需要跟踪对象是否应该移动。通过使用 keydown
和 keyup
事件,我们可以跟踪当前是否按下了左右键,然后只需在现有的 blockMove
函数中检查这些值:
//object to keep current state of keys
var keys = {
left: false,
right: false
};
function keydown(e) {
//remember "down" state
if (e.keyCode == 37)
keys.left = true;
if (e.keyCode == 39)
keys.right = true;
}
function keyup(e) {
//forget "down" state
if (e.keyCode == 37)
keys.left = false;
if (e.keyCode == 39)
keys.right = false;
}
var objX = 100;
function blockMove(){
//now check the key state, rather than the event object
if (keys.left) { //move left
objX -= 4;
}
if (keys.right) { //move right
objX += 4;
}
document.getElementById("object").style.left = objX + "px";
}
//Call the movement function every 20ms
window.setInterval(blockMove, 20);
<body onkeydown="keydown(event)" onkeyup="keyup(event)">
<div id=object style="height:10px;width:80px;background-color:red;position:absolute;top:50px;left:100px"></div>
</body>
正如下面评论中所讨论的,setInterval
仅保证调用函数之前的最短时间,并且可能会受到限制。除了四处移动 DOM 对象,学习这样的基础知识很好,但在某些时候你可能想看看 drawing directly onto <canvas>
elements and using requestAnimationFrame
来处理回调,因为它是为动画设计的,不像 setTimeout
/setInterval
.
我试图在按住某个键(在本例中为向左或向右箭头)时移动元素,但是当我按住某个键时,移动会延迟大约一秒钟。我使用了错误的事件还是我的代码有什么问题?
我正在使用 onKeyDown
事件来触发移动。
<head>
<script>
var objX = 100;
function blockMove(e){
if (e.keyCode == 37) { //move left
objX-=4;
document.getElementById("object").style.left = objX + "px";
} else if (e.keyCode == 39) { //move right
objX+=4;
document.getElementById("object").style.left = objX + "px";
}
}
</script>
</head>
<body onkeydown="blockMove(event)">
<div id=object style="height:10px;width:80px;background-color:red;position:absolute;top:50px;left:100px"></div>
</body>
请耐心等待,这有点长而且可能有问题: (如果你想自己做的话也剧透一下)
<head>
<script>
var objX = 100;
var leftDown = false;
var rightDown = false;
function blockMove(e){
if(e.keyCode == 37 && !leftDown) { //move left
leftDown = true;
objX-=4;
document.getElementById("object").style.left = objX + "px";
}else if(e.keyCode == 39 && !rightDown) { //move right
rightDown = true;
objX+=4;
document.getElementById("object").style.left = objX + "px";
}}
function stopMove(e)
{
if( e.keyCode == 37 )
leftDown = false;
if( e.keyCode == 39 )
rightDown = false;
}
function timer()
{
if( leftDown )
objX -= 4;
if( rightDown )
objX += 4;
document.getElementById("object").style.left = objX + "px";
}
setInterval(timer, 100);
</script>
</head>
<body onkeydown="blockMove(event)" onkeyup="stopMove(event)">
<div id=object
style="height:10px;width:80px;background-color:red;position:absolute;top:360px;left:100px"
></div>
</body>
而不是依赖于用户键盘重复率,这是最终导致多次调用 blockMove
的原因,您应该使用计时器来检查对象是否应该以一致的速率移动(每个在我下面的例子中是 20ms)。这意味着无论用户的重复率设置如何,这对所有用户来说都是一致的体验。
然后您需要跟踪对象是否应该移动。通过使用 keydown
和 keyup
事件,我们可以跟踪当前是否按下了左右键,然后只需在现有的 blockMove
函数中检查这些值:
//object to keep current state of keys
var keys = {
left: false,
right: false
};
function keydown(e) {
//remember "down" state
if (e.keyCode == 37)
keys.left = true;
if (e.keyCode == 39)
keys.right = true;
}
function keyup(e) {
//forget "down" state
if (e.keyCode == 37)
keys.left = false;
if (e.keyCode == 39)
keys.right = false;
}
var objX = 100;
function blockMove(){
//now check the key state, rather than the event object
if (keys.left) { //move left
objX -= 4;
}
if (keys.right) { //move right
objX += 4;
}
document.getElementById("object").style.left = objX + "px";
}
//Call the movement function every 20ms
window.setInterval(blockMove, 20);
<body onkeydown="keydown(event)" onkeyup="keyup(event)">
<div id=object style="height:10px;width:80px;background-color:red;position:absolute;top:50px;left:100px"></div>
</body>
正如下面评论中所讨论的,setInterval
仅保证调用函数之前的最短时间,并且可能会受到限制。除了四处移动 DOM 对象,学习这样的基础知识很好,但在某些时候你可能想看看 drawing directly onto <canvas>
elements and using requestAnimationFrame
来处理回调,因为它是为动画设计的,不像 setTimeout
/setInterval
.