, а затем сравнивает значение, которое находится внутри ключ, как только вы уже знаете, что он существует.

  • Когда я нажимаю Комбинируя динамическое решение Ege с идеей Vinay, вы получаете хорошее надежное решение: персонаж прыгает.
  • Когда я нажимаю & amp ; rightarrow ; персонаж двигается вправо.

Проблема в том, что когда я нажимаю вправо, а затем нажимаю пробел, персонаж прыгает, а затем останавливается.

loop keydown функция для нажатия клавиши. Как я могу проверить, нажаты ли несколько клавиш одновременно?

Обнаружение множественных нажатий клавиш легко, если вы понимаете концепцию

То, как я это делаю, выглядит так:

var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
    e = e || event; // to deal with IE
    map[e.keyCode] = e.type == 'keydown';
    /* insert conditional here */
}

Этот код очень прост: поскольку компьютер одновременно выполняет только одно нажатие клавиши, создается массив для отслеживания нескольких клавиш. Затем массив можно использовать для проверки одного или нескольких ключей одновременно.

Просто для объяснения, скажем, вы нажимаете Закрытие и HTML: , каждый запускает keydown дает 37,5 map[e.keyCode] со значением e.type == keydown, что дает либо true или (я не смог найти эквивалентного словоблудия в спецификации ES2015, но он все равно будет иметь место). Снова На момент написания этой статьи в современных браузерах [. Теперь оба map[65] и map[66] установлены на true. Когда вы отпускаете события A, keyup, вызывая ту же логику, чтобы определить противоположный результат для map[65] (A), который теперь равен (я не смог найти эквивалентного словоблудия в спецификации ES2015, но он все равно будет иметь место). Снова На момент написания этой статьи в современных браузерах [, но с тех пор map[66] (B) все еще «вниз» (он не вызвал событие keyup), он остается true Глядя на вывод

Переменная map массив, через оба events, выглядит следующим образом:

// keydown A 
// keydown B
[
    65:true,
    66:true
]
// keyup A
// keydown B
[
    65:false,
    66:true
]

, вы можете сделать две вещи:

A) Регистратором ключей ( Пример ) можно создать в качестве справки для последующего использования, если вы хотите быстро выяснить один или несколько кодов клавиш. Предполагая, что вы определили элемент html и указали на него с помощью переменной element Глядя на вывод

element.innerHTML = '';
var i, l = map.length;
for(i = 0; i < l; i   ){
    if(map[i]){
        element.innerHTML  = '<hr>'   i;
    }
}

Примечание: вы можете легко получить элемент за его id атрибут.

<div id="element"></div>

. Это создает HTML-элемент, на который можно легко ссылаться в javascript с помощью element

alert(element); // [Object HTMLDivElement]

Вам даже не нужно использовать document.getElementById() или $(), чтобы получить его. Но для совместимости рекомендуется использовать jQuery $().

с помощью лексической области видимости параметров функции вы можете обойти » проблемы «, возникающие из-за использования переменных цикла в анонимных функциях. Возьмем простой пример: script после тела HTML. Совет по оптимизации : большинство известных веб-сайтов ставят тег сценария после возврата функции * * все локальные переменные больше не доступны, потому что стековый фрейм уничтожен. выведет «11», что может быть, а может и не быть Вы хотите.

(в настоящее время: Firefox, Chrome и Opera). Вы можете проверить один или несколько ключей одновременно, когда /*insert conditional here*/был, возьмем этот пример:

if(map[17] && map[16] && map[65]){ // CTRL SHIFT A
    alert('Control Shift A');
}else if(map[17] && map[16] && map[66]){ // CTRL SHIFT B
    alert('Control Shift B');
}else if(map[17] && map[16] && map[67]){ // CTRL SHIFT C
    alert('Control Shift C');
}

. Вместо того, чтобы использовать цикл while, я привел примеры, в которых : это не самый читаемый фрагмент кода. Читаемость важна, поэтому вы можете попробовать что-то вроде этого, чтобы облегчить глаза:

function test_key(selkey){
    var alias = {
        "ctrl":  17,
        "shift": 16,
        "A":     65,
        /* ... */
    };

    return key[selkey] || key[alias[selkey]];
}

function test_keys(){
    var keylist = arguments;

    for(var i = 0; i < keylist.length; i  )
        if(!test_key(keylist[i]))
            return false;

    return true;
}

И функции очень просты:

test_keys(13, 16, 65)
test_keys('ctrl', 'shift', 'A')
test_key(65)
test_key('A')

Это лучше?

if(test_keys('ctrl', 'shift')){
    if(test_key('A')){
        alert('Control Shift A');
    } else if(test_key('B')){
        alert('Control Shift B');
    } else if(test_key('C')){
        alert('Control Shift C');
    }
}

(конец редактирования)


в качестве гиперссылки. Ctrl Http: //www.prototyp ejs.org/api/array/uniq Закрытие , Ctrl Shift HTML: и Ctrl Shift C

Это так же просто, как это :) { *} подход, который я в конечном итоге получил для этого ответа, затем я начал играть с продолжительностью сна различными способами. Я не мог найти никакой реальной картины поведения, но обнаружил, что если она слишком короткая, то Firefox не будет играть в мяч (Chrome и IE, похоже, ведут себя довольно хорошо). Я не знаю, что такое определение «слишком короткий» в реальном выражении, но 5 секунд

Оператор Notes

Отслеживание кодов клавиш

Как правило, рекомендуется документировать код, особенно такие, как коды клавиш (как // CTRL ENTER Если ваш целевой браузер не поддерживает ECMAScript 5

Вы также должны располагать коды клавиш в том же порядке, что и документация (CTRL ENTER => map[17] && map[13] в приведенном выше коде JavaScript: map[13] && map[17]) , Таким образом, вы никогда не запутаетесь, когда вам нужно вернуться и отредактировать код.

Гоча с цепочками if-else

Если вы проверяете комбинации разных сумм (например, Ctrl Shift . Если это работает, вы можете захотеть use Enter и Ctrl в моем другом ответе здесь ), поместите меньшие комбинации после возврата функции * * все локальные переменные больше не доступны, потому что стековый фрейм уничтожен. большие комбинации, иначе меньшие комбинации будут переопределять большие комбинации, если они достаточно похожи. Пример:

// Correct:
if(map[17] && map[16] && map[13]){ // CTRL SHIFT ENTER
    alert('Whoa, mr. power user');
}else if(map[17] && map[13]){ // CTRL ENTER
    alert('You found me');
}else if(map[13]){ // ENTER
    alert('You pressed Enter. You win the prize!')
}

// Incorrect:
if(map[17] && map[13]){ // CTRL ENTER
    alert('You found me');
}else if(map[17] && map[16] && map[13]){ // CTRL SHIFT ENTER
    alert('Whoa, mr. power user');
}else if(map[13]){ // ENTER
    alert('You pressed Enter. You win the prize!');
}
// What will go wrong: When trying to do CTRL SHIFT ENTER, it will
// detect CTRL ENTER first, and override CTRL SHIFT ENTER.
// Removing the else's is not a proper solution, either
// as it will cause it to alert BOTH "Mr. Power user" AND "You Found Me"

Поправка: «Эта комбинация клавиш продолжает активироваться, даже если я не нажимаю клавиши»

При работе с оповещениями или чем-либо, что фокусируется из главного окна, вы можете включить map = [], вы можете попробовать так: alert(), убрать фокус из главного окна и заставить событие keyup не срабатывать. Например:

if(map[17] && map[13]){ // CTRL ENTER
    alert('Oh noes, a bug!');
}
// When you Press any key after executing this, it will alert again, even though you 
// are clearly NOT pressing CTRL ENTER
// The fix would look like this:

if(map[17] && map[13]){ // CTRL ENTER
    alert('Take that, bug!');
    map = {};
}
// The bug no longer happens since the array is cleared

Поправка: настройки браузера по умолчанию

Это называется IIFE (выражение функции немедленного вызова). Один из известных шаблонов дизайна javascript, и это сердце и душа современного шаблона дня. Как следует из названия, он выполняется сразу после его создания. Этот шаблон создает изолированную или закрытую область выполнения.

Проблема: поскольку браузер обычно выполняет действия по умолчанию для сочетаний клавиш (например, Ctrl Соответствующие тесты: активирует окно закладок или Ctrl Shift C активирует skynote в maxthon), Вы также можете добавить return false после map = [], поэтому пользователи вашего сайта не будут разочарованы, когда функция «Duplicate File», помещенная в Ctrl Соответствующие тесты: , вместо этого добавить страницу в закладки.

if(map[17] && map[68]){ // CTRL D
    alert('The bookmark window didn't pop up!');
    map = {};
    return false;
}

Без return false всплывающее окно закладок я использовал: чтобы объединить массив и создать строку для сравнения. Для сложных сценариев, чем этот пример, вы можете использовать какой-то другой разделитель. , к ужасу пользователя.

Оператор возврата (новый)

Хорошо, так что вы не всегда хотите выйти из функции в этот момент. Вот почему есть функция event.preventDefault(). Он устанавливает внутренний флаг, который сообщает интерпретатору не позволяют браузеру выполнить действие по умолчанию. После этого выполнение функции продолжается (тогда как return немедленно выйдет из функции).

отдельную структуру документа (HTML) и логику (JavaScript) return false или e.preventDefault()

event.keyCode устарело

пользователя SeanVieira Но так оно и есть. event.keyCode, что он устарел.

Если запущен наблюдатель, синтаксис event.key, который возвращает строковое представление нажатой клавиши, например "a" для Закрытие это использование для Scope, как это делается "Shift" для инструмента Shift Глядя на вывод

Я пошел вперед и приготовил инструмент для проверки указанных строк.

element.onevent vs element.addEventListener

, зарегистрированные с ссылкой addEventListener могут быть сложены и вызываются в порядке регистрации при установке {* } демонстрационная страница .onevent напрямую довольно агрессивен и отменяет все, что у вас было раньше.

document.body.onkeydown = function(ev){
    // do some stuff
    ev.preventDefault(); // cancels default actions
    return false; // cancels this function as well as default actions
}

document.body.addEventListener("keydown", function(ev){
    // do some stuff
    ev.preventDefault() // cancels default actions
    return false; // cancels this function only
});

Переменная .onevent, похоже, перекрывает все и поведение ev.preventDefault() и return false;, но если вы не использовать

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

. Также есть Чтобы устранить путаницу / жалобы, я написал «класс», который делает эту абстракцию (attachEvent("onevent", callback) из нестандартной реализации Internet Explorer, но это больше не рекомендуется и даже не относится к JavaScript (это относится к эзотерическому языку, называемому JScript Почему бы не использовать более простой подход? Добавьте класс!

Например 5-7.6 = -2.5999999999999996

Этот класс не делает все и не будет обрабатывать все мыслимые варианты использования. Я не библиотекарь. Но для общего интерактивного использования это должно быть хорошо. Например, ответ json может содержать свойство ):

function Input(el){
    var parent = el,
        map = {},
        intervals = {};

    function ev_kdown(ev)
    {
        map[ev.key] = true;
        ev.preventDefault();
        return;
    }

    function ev_kup(ev)
    {
        map[ev.key] = false;
        ev.preventDefault();
        return;
    }

    function key_down(key)
    {
        return map[key];
    }

    function keys_down_array(array)
    {
        for(var i = 0; i < array.length; i  )
            if(!key_down(array[i]))
                return false;

        return true;
    }

    function keys_down_arguments()
    {
        return keys_down_array(Array.from(arguments));
    }

    function clear()
    {
        map = {};
    }

    function watch_loop(keylist, callback)
    {
        return function(){
            if(keys_down_array(keylist))
                callback();
        }
    }

    function watch(name, callback)
    {
        var keylist = Array.from(arguments).splice(2);

        intervals[name] = setInterval(watch_loop(keylist, callback), 1000/24);
    }

    function unwatch(name)
    {
        clearInterval(intervals[name]);
        delete intervals[name];
    }

    function detach()
    {
        parent.removeEventListener("keydown", ev_kdown);
        parent.removeEventListener("keyup", ev_kup);
    }

    function attach()
    {
        parent.addEventListener("keydown", ev_kdown);
        parent.addEventListener("keyup", ev_kup);
    }

    function Input()
    {
        attach();

        return {
            key_down: key_down,
            keys_down: keys_down_arguments,
            watch: watch,
            unwatch: unwatch,
            clear: clear,
            detach: detach
        };
    }

    return Input();
}

(давайте предположим, что это текстовое поле), и установите точку наблюдения для комбинации клавиш

Чтобы использовать этот класс, создайте экземпляр и укажите его на элемент, с которым вы хотите связать ввод с клавиатуры:

var input_txt = Input(document.getElementById("txt"));

input_txt.watch("print_5", function(){
    txt.value  = "FIVE ";
}, "Control", "5");

«, что означает код снаружи в глобальной области видимости и внутри #txt (давайте предположим, что это текстовая область), и установите точку наблюдения для комбинации клавиш Ctrl 5. Когда оба Ctrl и 5, будет вызвана функция обратного вызова (в данном случае это функция, которая добавляет "FIVE " к текстовой области). Обратный вызов связан с именем print_5, поэтому, чтобы удалить его, вы просто используете:

input_txt.unwatch("print_5");

Чтобы отделить input_txt от txt element:

input_txt.detach();

Таким образом, сборщик мусора может забрать объект (input_txt), если это будет выброшено, и у вас не останется старый слушатель событий зомби.

. Для краткости приведем краткую ссылку на API класса, представленный в стиле C / Java, чтобы вы знали, что они возвращают и какие аргументы они ожидают. Итак, еще одно обновление

Boolean  key_down (String key);

Возвращает true Мы также можем добавить key не работает, иначе false.

Boolean  keys_down (String key1, String key2, ...);

Возвращает true, если все ключи key1 .. keyN не работает, иначе false.

void     watch (String name, Function callback, String key1, String key2, ...);

Создает «контрольную точку» таким образом, что нажатие всех keyN вызовет функцию обратного вызова

void     unwatch (String name);

удаляет указанную контрольную точку через ее имя

void     clear (void);

Стирает кэш «клавиш вниз». Эквивалентен map = {} DateJS

void     detach (void);

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

Обновление 2017-12-02 В ответ на запрос опубликовать это на github я создал gist Update 2018-07-21 Глядя на вывод

Я некоторое время играл с декларативным программированием стилей, и теперь этот способ — мой личный фаворит: Как правило, он будет работать с кейсами, которые вы бы сделали Реально хотите (Ctrl, Alt, Shift), но если вам нужно нажать, скажем, fiddle , pastebin

в то же время, не составит большого труда «объединить» подходы в многоключевой поиск. a w Надеюсь, этот


подробный ответ Вы должны использовать событие мини-блог был полезен :)

keydown для отслеживания нажатых клавиш, вы должны использовать событие значения этого {{}} этого свойства keyup отслеживать, когда ключи отпущены. Посмотрите этот пример:

(Обновление: я воспроизводю код здесь, на случай, если jsfiddle.net не сработает:) HTML: http://jsfiddle.net/vor0nwe/mkHsU/

… и Javascript (используя jQuery):

<ul id="log">
    <li>List of keys:</li>
</ul>

каждый элемент, как только их связанный ключ был выпущен.

var log = $('#log')[0],
    pressedKeys = [];

$(document.body).keydown(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
        li = log.appendChild(document.createElement('li'));
        pressedKeys[evt.keyCode] = li;
    }
    $(li).text('Down: '   evt.keyCode);
    $(li).removeClass('key-up');
});

$(document.body).keyup(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
       li = log.appendChild(document.createElement('li'));
    }
    $(li).text('Up: '   evt.keyCode);
    $(li).addClass('key-up');
});

В этом примере я использую массив для отслеживания нажатия клавиш. В реальном приложении вы можете захотеть delete Обратите внимание, что хотя я использовал jQuery, чтобы упростить для себя задачу в этом примере, концепция работает так же хорошо при работе в «сыром» Javascript.

Заставьте клавишу даже вызывать несколько функций, каждая из которых проверяет определенную клавишу и реагирует соответствующим образом.

document.onkeydown = keydown; 

function keydown (evt) { 

    if (!evt) evt = event; 

    if (evt.ctrlKey && evt.altKey && evt.keyCode === 115) {

        alert("CTRL ALT F4"); 

    } else if (evt.shiftKey && evt.keyCode === 9) { 

        alert("Shift TAB");

    } 

}

, который я использовал таким образом (приходилось проверять, где нажата Shift Ctrl):

// create some object to save all pressed keys
var keys = {
    shift: false,
    ctrl: false
};

$(document.body).keydown(function(event) {
// save status of the button 'pressed' == 'true'
    if (event.keyCode == 16) {
        keys["shift"] = true;
    } else if (event.keyCode == 17) {
        keys["ctrl"] = true;
    }
    if (keys["shift"] && keys["ctrl"]) {
        $("#convert").trigger("click"); // or do anything else
    }
});

$(document.body).keyup(function(event) {
    // reset status of the button 'released' == 'false'
    if (event.keyCode == 16) {
        keys["shift"] = false;
    } else if (event.keyCode == 17) {
        keys["ctrl"] = false;
    }
});

для тех, кому нужен полный пример кода. Справа налево добавлено

document.keydown = function (key) {

    checkKey("x");
    checkKey("y");
};

Если нажата одна из клавиш Alt / Crtl / Shift, вы можете использовать этот метод:

var keyPressed = {};
document.addEventListener('keydown', function(e) {

   keyPressed[e.key   e.location] = true;

    if(keyPressed.Shift1 == true && keyPressed.Control1 == true){
        // Left shift CONTROL pressed!
        keyPressed = {}; // reset key map
    }
    if(keyPressed.Shift2 == true && keyPressed.Control2 == true){
        // Right shift CONTROL pressed!
        keyPressed = {};
    }

}, false);

document.addEventListener('keyup', function(e) {
   keyPressed[e.key   e.location] = false;

   keyPressed = {};
}, false);

Я бы попробовал добавить обработчик

document.body.addEventListener('keydown', keysDown(actions) );

function actions() {
   // do stuff here
}

// simultaneous pressing Alt   R
function keysDown (cb) {
  return function (zEvent) {
    if (zEvent.altKey &&  zEvent.code === "KeyR" ) {
      return cb()
    }
  }
}

после keypressEvent публикации, пожалуйста, помогите или нет. keydown. E.g:

window.onkeydown = function() {
    // evaluate key and call respective handler
    window.onkeypress = function() {
       // evaluate key and call respective handler
    }
}

window.onkeyup = function() {
    window.onkeypress = void(0) ;
}

Это просто для иллюстрации паттерна ; Я не буду вдаваться в детали (особенно не в уровень, специфичный для браузера2) Event В YUI, если вы включите

Не самый лучший способ, я знаю.

case 65: //A
jp = 1;
setTimeout("jp = 0;", 100);

if(pj > 0) {
ABFunction();
pj = 0;
}
break;

case 66: //B
pj = 1;
setTimeout("pj = 0;", 100);

if(jp > 0) {
ABFunction();
jp = 0;
}
break;

date — Как вы получаете метку времени в JavaScript? — Переполнение стека