Может ли jQuery .keypress() обнаружить более одного ключа одновременно?

Есть ли способ для jQuery обнаружить, что более чем одна клавиша была нажата одновременно?

Есть ли альтернатива, позволяющая одновременно нажимать две клавиши?

6 ответов

Решение

Чтобы обнаружить несколько нажатых клавиш, используйте keydown а также keyup События.

var keys = {};

$(document).keydown(function (e) {
    keys[e.which] = true;
});

$(document).keyup(function (e) {
    delete keys[e.which];
});

Я собрал демо здесь: http://jsfiddle.net/gFcuU/. Это забавно, хотя я заметил, что моя клавиатура способна распознавать не более 6 клавиш.

Это зависит. Для "нормальных" клавиш, что означает "не Shift", " Ctrl", " ALT"(CMD), ответ "нет", обработчик события будет зависать / срабатывать в очереди, один за другим.

Для ключей-модификаторов, о которых я упоминал выше, у объекта события есть свойство.

Пример:

$(document).bind('keypress', function(event) {
    if( event.which === 65 && event.shiftKey ) {
        alert('you pressed SHIFT+A');
    }
});

Jsfiddle demo.

Другие свойства:

  • event.ctrlKey
  • event.altKey
  • event.metaKey

Если вы просто хотите запустить обработчик при последовательном нажатии нескольких клавиш, попробуйте что-то вроде:

jQuery.multipress = function (keys, handler) {
    'use strict';

    if (keys.length === 0) {
        return;
    }

    var down = {};
    jQuery(document).keydown(function (event) {
        down[event.keyCode] = true;
    }).keyup(function (event) {
        // Copy keys array, build array of pressed keys
        var remaining = keys.slice(0),
            pressed = Object.keys(down).map(function (num) { return parseInt(num, 10); }),
            indexOfKey;
        // Remove pressedKeys from remainingKeys
        jQuery.each(pressed, function (i, key) {
            if (down[key] === true) {
                down[key] = false;
                indexOfKey = remaining.indexOf(key);
                if (indexOfKey > -1) {
                    remaining.splice(indexOfKey, 1);
                }
            }
        });
        // If we hit all the keys, fire off handler
        if (remaining.length === 0) {
            handler(event);
        }
    });
};

Например, стрелять по ул,

jQuery.multipress([83, 84], function () { alert('You pressed s-t'); })

Вот решение jQuery, основанное на ответе Maciej /questions/15908143/mozhet-li-jquery-keypress-obnaruzhit-bolee-odnogo-klyucha-odnovremenno/15908146#15908146

// the array to add pressed keys to
var keys = [];
// listen for which key is pressed
document.addEventListener('keydown', (event) => {
    if ($.inArray(event.keyCode, keys) == -1) {
        keys.push(event.keyCode);
    }
    console.log('keys array after pressed = ' + keys);
});
// listen for which key is unpressed
document.addEventListener('keyup', (event) => {
    // the key to remove
    var removeKey = event.keyCode;
  // remove it
    keys = $.grep(keys, function(value) {
        return value != removeKey;
    });
    console.log('keys array after unpress = ' + keys);
});
// assign key number to a recognizable value name
var w = 87;
var d = 68;
var s = 83;
var a = 65;
// determine which keys are pressed
document.addEventListener('keydown', (event) => {
  if ($.inArray(w, keys) != -1 && $.inArray(d, keys) != -1) { // w + d
    console.log('function for w + d combo');
  } else if ($.inArray(s, keys) != -1 && $.inArray(a, keys) != -1) { // s + a
    console.log('function for s + a combo');
  }
})

демонстрация скрипки

https://jsfiddle.net/Hastig/us00zdo6/

Нету. keypress будет срабатывать для каждой отдельной нажатой клавиши - за исключением клавиш-модификаторов, таких как CTRL, ALT и SHIFT, вы можете комбинировать их с другими клавишами, если это только одна другая клавиша.

Если вы используете esma6, вы можете сделать следующее, используя наборы.

const KEYS = new Set();

$(document).keydown(function (e) {
   KEYS.add(e.which);
   if(KEYS.has(12) && KEYS.has(31)){
      //do something
   }
});
$(document).keyup(function (e) {
   KEYS.delete(e.which);
});

И если вы хотите, чтобы пользователь нажал их вместе, вы можете сделать:

const KEYS = new Set(); // for other purposes
const RECENT_KEYS = new Set(); // the recently pressed keys
const KEY_TIMELAPSE = 100 // the miliseconds of difference between keys

$(document).keydown(function (e) {
   KEYS.add(e.which);
   RECENT_KEYS.add(e.which);
   setTimeout(()=>{
      RECENT_KEYS.delete(e.which);
   }, KEY_TIMELAPSE);
   if(RECENT_KEYS.has(37) && RECENT_KEYS.has(38)){
      // Do something
   }
});
$(document).keyup(function (e) {
   KEYS.delete(e.which);
   RECENT_KEYS.delete(e.which);
});

Вот кодовая ручка https://codepen.io/Programador-Anonimo/pen/NoEeKM?editors=0010

Поскольку моя суть истекла (никто не использовал ее:(), я решил обновить ответ, добавив решение 2017 года. Проверьте ниже.

Вы можете использовать мой плагин для jquery, чтобы обнаружить ярлыки.

Это в основном кеширование событий и получение того, какие клавиши нажаты в данный момент. Если все клавиши нажаты, она активирует функцию.

https://github.com/maciekpaprocki/bindShortcut (просрочено!)

У вас есть небольшое объяснение, как использовать его в файле readme. Надеюсь это поможет. Обратная связь более чем ценится.

Редактировать 2017:

Сейчас 2017 год, и нам не нужны плагины jQuery для решения подобных задач. Короче вам понадобится что-то вроде этого:

let pressed = {};

document.addEventListener('keydown', (event) => {
   pressed[event.key] = true;
});
document.addEventListener('keyup', (event) => {
   delete pressed[event.key];
});

//and now write your code
document.addEventListener('keydown', (event) => {
  if(pressed[firstKey]&&pressed[secondKey]){
    //dosomething
  }
});

В старых браузерах могут быть некоторые причуды, однако в IE9 все должно работать нормально, за исключением небольшого количества ОС, которые не поддерживают правильное делегирование событий (супер старая Ubuntu и т. Д.). Нет никакого способа исправить это в них, поскольку это не проблема браузера.

Есть некоторые причуды в новых маках, связанных с булевыми ключами, такие как, например, заглавные буквы.

Подробнее: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent

Согласно решению @David Tang, вот быстрая и грязная настройка для захвата комбинации Shift+Ctrl+A:

var pressedKeys = {};

function checkPressedKeys() {
    var shiftPressed=false, ctrlPressed=false, aPressed=false;
    for (var i in pressedKeys) {
        if (!pressedKeys.hasOwnProperty(i)) continue;
        if(i==16){
            shiftPressed=true;
        }
        else if(i==17){
            ctrlPressed=true;
        }
        else if(i==65){
            aPressed=true;
        }
    }
    if(shiftPressed && ctrlPressed && aPressed){
        //do whatever you want here.
    }
}


$(document).ready(function(){
    $(document).keydown(function (e) {
        pressedKeys[e.which] = true;
        checkPressedKeys();
    });

    $(document).keyup(function (e) {
        delete pressedKeys[e.which];
    });
});
Другие вопросы по тегам