通过按键移动元素(多次)

问题描述 投票:0回答:3

对角线移动不起作用并在左长按/右同时按下时出现问题

但是按两次按键,船就会变得疯狂!

$(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();
});
jquery keypress
3个回答
9
投票

我搞乱了类似的事情,这是我遇到的一个有效的解决方案。

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 事件删除相应的键。

在此解决方案中,您有两种方法来管理正在移动的元素的速度。

  1. 间隔的更新频率。 (上面的演示中为 20 毫秒)
  2. 平面每次移动的像素数。 (上面演示中的 5)

我发现 20 毫秒的间隔频率可以让你的运动相当平滑。

我意识到这是一个非常古老的线程,但我想我无论如何都会做出贡献。


2
投票

关于那个间隔,

http://jsfiddle.net/fbFuW/21/

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);

2
投票

依靠键盘事件来移动元素将使其依赖于操作系统按键间隔延迟。 相反,使用游戏间隔并检查存储在对象内的按下的按键

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>

© www.soinside.com 2019 - 2024. All rights reserved.