按住时 KeyDown 不会持续触发
KeyDown doesn't continuously fire when pressed and hold
我有这个Plunkr,
这包含一个 div
,我在其上绑定了一个 keydown
事件。按右箭头或左箭头,div 应该开始移动。
这在所有浏览器中都有效,但是当 按下并按住 键时,会立即触发第一个 keydown 事件(div 一旦移动),并且它等待一个时间间隔,然后继续移动。
所以这意味着 keydown
事件一旦被触发,然后浏览器等待检测是否还有后续的 keyUp
事件,然后在很短的时间之后(当没有 keyup ),它会继续触发 keydown
事件。
(看问题,关注window,按住右箭头,div应该移动一次5px,然后等待,然后再次继续移动)
问题: 有没有什么办法,让我一直按住这个键,div应该立即开始移动,而不用等到检测到后续的按键操作(一次)?
$(function() {
$(window).keydown(function(e) {
console.log(e.keyCode)
if (e.keyCode == 39)
move(5, 'left', $('.mover'))
else if (e.keyCode == 37)
move(-5, 'left', $('.mover'))
})
})
function move(offset, direction, target) {
console.log($(target))
$(target).css(direction, (parseInt($(target).css(direction)) + offset) + 'px')
}
.mover {
height: 50px;
width: 50px;
display: inline-block;
background: black;
position: absolute;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='mover'></div>
当您要跟踪的键上发生 keydown 事件时,将此信息存储在某个映射或标记中。
当 keyup 事件发生时,清除给定键的标志。
然后,在计时器上,您可以轮询键映射的状态,并根据按下的任何键方向移动对象。
可能有比轮询更好的解决方案,但我不知道除了轮询之外还有什么方法可以测试按键是否按下。
在键入时,还需要检查是否需要中断移动对象。
一个解决方案是连续 运行 循环中的移动函数,直到发生 keyup
if (e.keyCode == 39){
var stop = setInterval(function(){
move(5, 'left', $('.mover'))
}, 25);
window.on("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.off("keyup", arguments.callee);
})
} else if //etc...
我会在超时时提出一些建议,例如
http://codepen.io/kevrowe/pen/qEgGVO
$(function() {
var direction,
movingTimeout = -1;
$(window).on('keydown', function(e) {
if (e.keyCode == 39) {
direction = 'right';
} else if (e.keyCode == 37) {
direction = 'left';
}
startMoving(direction);
});
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = -1;
}
function startMoving(direction) {
if (movingTimeout === -1) {
loop(direction);
}
}
function loop(direction) {
move(direction === 'left' ? -5 : 5, $('.mover'));
movingTimeout = setTimeout(loop, 10, direction);
}
function move(offset, $target) {
$target.css('left', (parseInt($target.css('left')) + offset) + 'px')
}
$(window).on('keyup', function(e) {
stopMoving();
});
})
对于那些可能感兴趣的人,这是处理双向移动的另一种方法。例如:up
+ right
键 = "North East" 方向:
const FPS = 60;
const STEP = 5;
const UP_KEY = 90; // Z
const DOWN_KEY = 83; // S
const LEFT_KEY = 81; // Q
const RIGHT_KEY = 68; // D
const pressedKeys = [];
let movingTimeout = null;
function handleKeyDown(e) {
pressedKeys[e.keyCode] = true;
switch(e.keyCode) {
case DOWN_KEY:
case LEFT_KEY:
case RIGHT_KEY:
case UP_KEY:
e.preventDefault();
startMoving();
}
}
function handleKeyUp(e) {
pressedKeys[e.keyCode] = false;
const shouldStop = !pressedKeys[UP_KEY]
&& !pressedKeys[DOWN_KEY]
&& !pressedKeys[LEFT_KEY]
&& !pressedKeys[RIGHT_KEY]
;
if(shouldStop) {
stopMoving();
}
}
function startMoving() {
if(!movingTimeout){
loop();
}
}
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = null;
}
function loop() {
const x = pressedKeys[RIGHT_KEY] ? STEP
: pressedKeys[LEFT_KEY] ? -STEP : 0;
const y = pressedKeys[DOWN_KEY] ? STEP
: pressedKeys[UP_KEY] ? -STEP : 0;
move(x, y);
movingTimeout = setTimeout(loop, 1000 / FPS);
}
function move(x, y) {
// Implement you own logic here for positioning / handling collisions
// Ex: store.dispatch({ type: "MOVE_PLAYER", x, y });
console.log(`Moving ${x} ${y} !`);
}
window.addEventListener('keydown', e => handleKeyDown(e));
window.addEventListener('keyup', e => handleKeyUp(e));
希望对您有所帮助。
干杯!
纯粹javascript
<input id="some" type="text">
var input=document.getElementById("some");
input.addEventListener("keydown",function(e){
if (e.which == 40) {
var stop = setInterval(function(){
console.log("ss:");
}, 60);
window.addEventListener("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.removeEventListener("keyup", arguments.callee);
})
}
})
我有这个Plunkr,
这包含一个 div
,我在其上绑定了一个 keydown
事件。按右箭头或左箭头,div 应该开始移动。
这在所有浏览器中都有效,但是当 按下并按住 键时,会立即触发第一个 keydown 事件(div 一旦移动),并且它等待一个时间间隔,然后继续移动。
所以这意味着 keydown
事件一旦被触发,然后浏览器等待检测是否还有后续的 keyUp
事件,然后在很短的时间之后(当没有 keyup ),它会继续触发 keydown
事件。
(看问题,关注window,按住右箭头,div应该移动一次5px,然后等待,然后再次继续移动)
问题: 有没有什么办法,让我一直按住这个键,div应该立即开始移动,而不用等到检测到后续的按键操作(一次)?
$(function() {
$(window).keydown(function(e) {
console.log(e.keyCode)
if (e.keyCode == 39)
move(5, 'left', $('.mover'))
else if (e.keyCode == 37)
move(-5, 'left', $('.mover'))
})
})
function move(offset, direction, target) {
console.log($(target))
$(target).css(direction, (parseInt($(target).css(direction)) + offset) + 'px')
}
.mover {
height: 50px;
width: 50px;
display: inline-block;
background: black;
position: absolute;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='mover'></div>
当您要跟踪的键上发生 keydown 事件时,将此信息存储在某个映射或标记中。
当 keyup 事件发生时,清除给定键的标志。
然后,在计时器上,您可以轮询键映射的状态,并根据按下的任何键方向移动对象。
可能有比轮询更好的解决方案,但我不知道除了轮询之外还有什么方法可以测试按键是否按下。
在键入时,还需要检查是否需要中断移动对象。
一个解决方案是连续 运行 循环中的移动函数,直到发生 keyup
if (e.keyCode == 39){
var stop = setInterval(function(){
move(5, 'left', $('.mover'))
}, 25);
window.on("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.off("keyup", arguments.callee);
})
} else if //etc...
我会在超时时提出一些建议,例如
http://codepen.io/kevrowe/pen/qEgGVO
$(function() {
var direction,
movingTimeout = -1;
$(window).on('keydown', function(e) {
if (e.keyCode == 39) {
direction = 'right';
} else if (e.keyCode == 37) {
direction = 'left';
}
startMoving(direction);
});
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = -1;
}
function startMoving(direction) {
if (movingTimeout === -1) {
loop(direction);
}
}
function loop(direction) {
move(direction === 'left' ? -5 : 5, $('.mover'));
movingTimeout = setTimeout(loop, 10, direction);
}
function move(offset, $target) {
$target.css('left', (parseInt($target.css('left')) + offset) + 'px')
}
$(window).on('keyup', function(e) {
stopMoving();
});
})
对于那些可能感兴趣的人,这是处理双向移动的另一种方法。例如:up
+ right
键 = "North East" 方向:
const FPS = 60;
const STEP = 5;
const UP_KEY = 90; // Z
const DOWN_KEY = 83; // S
const LEFT_KEY = 81; // Q
const RIGHT_KEY = 68; // D
const pressedKeys = [];
let movingTimeout = null;
function handleKeyDown(e) {
pressedKeys[e.keyCode] = true;
switch(e.keyCode) {
case DOWN_KEY:
case LEFT_KEY:
case RIGHT_KEY:
case UP_KEY:
e.preventDefault();
startMoving();
}
}
function handleKeyUp(e) {
pressedKeys[e.keyCode] = false;
const shouldStop = !pressedKeys[UP_KEY]
&& !pressedKeys[DOWN_KEY]
&& !pressedKeys[LEFT_KEY]
&& !pressedKeys[RIGHT_KEY]
;
if(shouldStop) {
stopMoving();
}
}
function startMoving() {
if(!movingTimeout){
loop();
}
}
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = null;
}
function loop() {
const x = pressedKeys[RIGHT_KEY] ? STEP
: pressedKeys[LEFT_KEY] ? -STEP : 0;
const y = pressedKeys[DOWN_KEY] ? STEP
: pressedKeys[UP_KEY] ? -STEP : 0;
move(x, y);
movingTimeout = setTimeout(loop, 1000 / FPS);
}
function move(x, y) {
// Implement you own logic here for positioning / handling collisions
// Ex: store.dispatch({ type: "MOVE_PLAYER", x, y });
console.log(`Moving ${x} ${y} !`);
}
window.addEventListener('keydown', e => handleKeyDown(e));
window.addEventListener('keyup', e => handleKeyUp(e));
希望对您有所帮助。
干杯!
纯粹javascript
<input id="some" type="text">
var input=document.getElementById("some");
input.addEventListener("keydown",function(e){
if (e.which == 40) {
var stop = setInterval(function(){
console.log("ss:");
}, 60);
window.addEventListener("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.removeEventListener("keyup", arguments.callee);
})
}
})