开发者

Disable arrow keys from scrolling only when user is interacting with <canvas>

开发者 https://www.devze.com 2023-04-10 02:49 出处:网络
I have added an event listener in JS to listen for keyup/keydown events, I am attempting to move a sprite across the HTML canvas. I have that mostly working, but the page is being scrolled when the us

I have added an event listener in JS to listen for keyup/keydown events, I am attempting to move a sprite across the HTML canvas. I have that mostly working, but the page is being scrolled when the user presses the arrow keys.

I am returning false, and that does not seem to work. In addition, my understanding is that returning false in this manner would disable arrow button scrolling for the entire page. I would like to only disable this while the user is interacting with the canvas itself.

Here is my event listener:

addEventListener('keydown', function(e){
    move = false;
    x = false;
    y = false;
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (e) keycode = e.which;
    switch(keycode){
        case 37:
            move = true;
            x = 'negative';
        break;
        case 38:
            move = true;
            y = 'negative'
        break;
        case 39:
            move = true;
            x = 'positive'
        break;
        case 40:
            move = true;
            y = 'positive'
        break;
    }
    if(move){
        animation.move(x,y);
    }
    return false;
})

Edit:

The below answer has a good idea of how to make sure that the canvas is focused, but I am still puzzled why returning false in my EventListener function which returns fa开发者_运维知识库lse is not disabling scrolling.


As long as you are giving your canvas focus somehow (ie canvas.tabIndex = 1;) then you can just add e.preventDefault() right before your return false and it will work.

Example:

http://jsfiddle.net/faAkN/


I had a similar problem, and came up with a fix.

Here's what I came up with:

function $(){
  return document.querySelector.apply(document,arguments);
}
var canvas = $('canvas'),
    keysDown = []; // You can also define this as an object, {}
canvas.tabIndex = 0;
canvas.onclick = function(e){
  document.body.scrollTop = canvas.offsetTop; // scrolls to canvas element
  canvas.focus(); // re-focuses canvas in case the scroll unfocused it
}
canvas.onkeydown = canvas.onkeyup = function(e){
  keysDown[e.keyCode] = e.type == 'keydown';
  e.preventDefault();
  return false;
}
function isDown(key){
  return keysDown[key];
}
function resetMap(){
  keysDown = [];
  return false;
}

To check if a key is down, use isDown(keycode) either in an interval loop or in a keydown function.

For a regular key listener:

canvas.onkeydown = canvas.onkeyup = function(e){
  // [...]
  if(isDown(17) && isDown(32)){ // Ctrl + Space
    alert('Ctrl and Space were pressed');
    resetMap();
  }
  e.preventDefault();
  return false;
}

For a rapid key listener similar to ActionScript 2.0's Key.isDown

function KeyLoop(){
  if(isDown(17) && isDown(32)){ // Ctrl + Space
    console.log('Lots of text');
    resetMap();
  }
  setTimeout(keyLoop,1000/24); // @ 24 fps
}
keyLoop();

I put a different action here for two reasons: 1) Mixing alert() with a repeating interval is never a good idea, and 2) to demonstrate the lack of delay, which is what makes this similar to the AS2 Key.isDown() function. To see the logged text, bring up firebug or a regular JavaScript console. In Chrome, that's CtrlShiftJ. In Firefox, CtrlShiftK.


This should fix your scrolling problem by focusing on the element when you click the canvas. An added benefit is that you can check for multiple keys at once since you're using keysDown[] as an abstraction from the original event, making an 8-directional game easy to make.


Have you tried something like this?

<script type="text/javascript">
    canvas_active = false;
</script>

<canvas onfocus="javascript: canvas_active = true;" onblur="javascript: canvas_active = false;" />

Then in your current method check to see if the canvas_active is true and if so, return false, else return true. This would only work if the canvas is focused the whole time they are moving it, of course.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号