对角线移动不起作用并在左长按/右同时按下时出现问题
但是按两次按键,船就会变得疯狂!
$(document).bind('keydown', function(e) {
var box = $("#plane"),
left = 37,
up = 38,
right = 39,
down = 40
if (e.keyCode == left) {
box.animate({left: "-=5000"},3000);
}
if (e.keyCode == up) {
box.animate({top: "-=5000"},3000);
}
if (e.keyCode == right) {
box.animate({left:"+=5000"},3000);
}
if (e.keyCode == down) {
box.animate({top: "+=5000"},3000);
}
});
$(document).bind('keyup', function() {
$('#plane').stop();
});
我搞乱了类似的事情,这是我遇到的一个有效的解决方案。
setInterval(movePlane, 20);
var keys = {}
$(document).keydown(function(e) {
keys[e.keyCode] = true;
});
$(document).keyup(function(e) {
delete keys[e.keyCode];
});
function movePlane() {
for (var direction in keys) {
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 37) {
$("#plane").animate({left: "-=5"}, 0);
}
if (direction == 38) {
$("#plane").animate({top: "-=5"}, 0);
}
if (direction == 39) {
$("#plane").animate({left: "+=5"}, 0);
}
if (direction == 40) {
$("#plane").animate({top: "+=5"}, 0);
}
}
}
延迟的问题似乎是大多数浏览器都会接受第一个输入(在 keyDown 上),然后在一遍又一遍地运行函数之前有半秒的延迟。如果我们不记得按下按键时的功能,而是有一个时间间隔检查一个关联数组,在该数组中存储按下的键,这似乎可以平滑移动。它还允许同时按下多个键,这意味着对角线移动。然后我们将使用 keyup 事件删除相应的键。
在此解决方案中,您有两种方法来管理正在移动的元素的速度。
我发现 20 毫秒的间隔频率可以让你的运动相当平滑。
我意识到这是一个非常古老的线程,但我想我无论如何都会做出贡献。
关于那个间隔,
var leftDown, rightDown, upDown, downDown,leftKey,upKey,rightKey,downKey;
var box = $("#plane");
function keye(e) {
console.log(e.keyCode);
var $key = e.keyCode;
$(document).keydown(function(e) {
if (e.keyCode == left && $key != left) leftDown = true;
if (e.keyCode == right && $key != right) rightDown = true;
if (e.keyCode == down && $key != down) downDown = true;
if (e.keyCode == up && $key != up) upDown = true;
}).keyup(function(e) {
if (e.keyCode == left) leftDown = false;
if (e.keyCode == right) rightDown = false;
if (e.keyCode == down) downDown = false;
if (e.keyCode == up) upDown = false;
});
if (e.keyCode == left) {
leftKey = true;
}
if (e.keyCode == up) {
upKey = true;
}
if (e.keyCode == right) {
rightKey = true;
}
if (e.keyCode == down) {
downKey = true;
}
}
$("body").keydown(function(){
keye(event);
});
$("body").keyup(function(e){
if (e.keyCode == left) {
leftKey = false;
}
if (e.keyCode == up) {
upKey = false;
}
if (e.keyCode == right) {
rightKey = false;
}
if (e.keyCode == down) {
downKey = false;
}
});
setInterval(function() {
if (leftDown) {
box.css('left', '-=5');
}
if (rightDown) {
box.css('left', '+=5');
}
if (downDown) {
box.css('top', '+=5');
}
if (upDown) {
box.css('top', '-=5');
}
if (upKey) {
box.css("top", "-=5");
}
if (rightKey) {
box.css("left", "+=5");
}
if (downKey) {
box.css("top", "+=5");
}
if (leftKey) {
box.css("left", "-=5");
}
},20);
依靠键盘事件来移动元素将使其依赖于操作系统按键间隔延迟。 相反,使用游戏间隔并检查存储在对象内的按下的按键
在
keydown keyup
事件中,如果 event.which
返回的 keyCode 是 >=37 && <=40
则表示使用了箭头键。在 K
(键)对象内存储键编号属性的布尔值。
在
window.requestAnimationFrame
内,如果键号属性(在我们的 x
对象内)为 y
(K
),则增加或减少元素的 true
、if(K[37])
位置。
同时使用↑和→沿对角线移动元素需要补偿对角线距离:
1 / Math.sqrt(2)
(0.7071..)
const Player = {
el: document.getElementById('player'),
x: 200,
y: 100,
speed: 2,
move() {
this.el.style.transform = `translate(${this.x}px, ${this.y}px)`;
}
};
const K = {
fn(ev) {
const k = ev.which;
if (k >= 37 && k <= 40) {
ev.preventDefault();
K[k] = ev.type === "keydown"; // If is arrow
}
}
};
const update = () => {
let dist = K[38] && (K[37] || K[39]) || K[40] && (K[37] || K[39]) ? 0.707 : 1;
dist *= Player.speed;
if (K[37]) Player.x -= dist;
if (K[38]) Player.y -= dist;
if (K[39]) Player.x += dist;
if (K[40]) Player.y += dist;
Player.move();
}
document.addEventListener('keydown', K.fn);
document.addEventListener('keyup', K.fn);
(function engine() {
update();
window.requestAnimationFrame(engine);
}());
#player{
position: absolute;
left: 0; top: 0;
width: 20px; height: 20px;
background: #000; border-radius: 50%;
}
Click here to focus, and use arrows
<div id="player"></div>
或者这里有一个轻微的重制,使用
new Set()
来记录当前按下的键盘按键,并使用 new Map()
来注册每个按下的键的功能:
const Player = {
el: document.querySelector("#player"),
x: 200,
y: 100,
speed: 2,
move() {
this.el.style.translate = `${this.x}px ${this.y}px`;
}
};
const getDistance = () => Player.speed * ((kbd.has("ArrowUp") || kbd.has("ArrowDown")) && (kbd.has("ArrowLeft") || kbd.has("ArrowRight")) ? 0.707 : 1);
// Watch pressed keyboard keys:
const kbd = new Set();
const handleArrowKeys = (evt) => {
if (!keyActions.has(evt.key)) return; // Do nothing. Not a registered key
evt.preventDefault(); // Prevent browser default action
kbd[evt.type === "keydown" ? "add" : "delete"](evt.key); // Add or delete a key
};
addEventListener("keydown", handleArrowKeys);
addEventListener("keyup", handleArrowKeys);
// Register keyboard keys actions
// Set a desired function for every desired key:
const keyActions = new Map();
keyActions.set("ArrowRight", () => {
Player.x += getDistance();
});
keyActions.set("ArrowLeft", () => {
Player.x -= getDistance();
});
keyActions.set("ArrowUp", () => {
Player.y -= getDistance();
});
keyActions.set("ArrowDown", () => {
Player.y += getDistance();
});
const engine = () => {
// Trigger a keyAction for pressed keys
kbd.forEach((key) => keyActions.get(key)());
Player.move();
requestAnimationFrame(engine);
};
engine();
#player { position: absolute; left: 0; top: 0; width: 20px; height: 20px; background: #000; border-radius: 50%; }
Click here to focus, and use arrow keys
<div id="player"></div>