【问题标题】:move element with keypress (multiple)使用按键移动元素(多个)
【发布时间】:2011-11-10 00:59:54
【问题描述】:

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

但是在双键按下时,船会发疯!

$(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();
});

【问题讨论】:

  • +1! GRrre评论! :D 呵呵,我差点把咖啡吐了!
  • 很高兴让你开心。吃完午饭回来我会试试的
  • 我已经在努力了! (有时讨厌谷歌)当你吃饱了告诉我!

标签: jquery keypress


【解决方案1】:

依靠键盘事件来移动元素将使其依赖于操作系统的键间隔延迟。 改为使用游戏间隔并检查存储在 Object 中的按键

keydown keyup 事件中,如果event.which 返回的keyCode 是>=37 && <=40,则表示使用了箭头键。在 K (keys) 对象中存储键号属性的布尔值。

间隔:

如果键号属性(在我们的K 对象内)是true (if(K[37])),则在window.requestAnimationFrame 内增加或减少元素的xy 位置。

对角线运动:

同时使用 沿对角线移动元素需要对对角线距离进行补偿: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>

【讨论】:

    【解决方案2】:

    我搞砸了类似的事情,这是我遇到的一个可行的解决方案。

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

    Demo

    延迟的问题似乎是大多数浏览器会接受第一个输入(在 keyDown 上),然后在一遍又一遍地运行函数之前会有半秒的延迟。如果我们不记得 keydown 上的函数,而是有一个间隔检查一个关联数组,我们存储了哪些键被按下,这似乎可以平滑移动。它还允许同时按下多个键,这意味着对角线移动。然后我们将使用 keyup 事件删除相应的键。

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

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

    我发现 20 毫秒的间隔频率可以让您的运动相当顺畅。

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

    【讨论】:

    • 您的图像不再工作,但如果您将任何链接粘贴到图像,小提琴将工作......很好的例子。
    • 用工作图像更新了小提琴。感谢您的提醒。
    【解决方案3】:

    关于那个间隔,

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

    【讨论】:

    • +1 感谢创世纪!这看起来很……长! :) 但它的工作原理......几乎。还有一些停止延迟。尝试按住“左”,然后快速切换到“右”。船会熄火。 :\
    • @roXon:抱歉,请按 F5。我得到了一些虚拟的 if 语句。
    • @roXon:取得了一些进展,但它在未经批准的情况下到处乱飞! jsfiddle.net/fbFuW/17
    • 您的编辑无效! (你看看我的问题编辑。到目前为止我做得最好)
    • 在 Mozilla 中,船没有移动!附言在 Chrome 中......它只是规则! :D
    猜你喜欢
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多