Проверить, не нажата ли клавиша? - PullRequest
76 голосов
/ 01 декабря 2009

Есть ли способ определить, не активен ли ключ в JavaScript?

Я знаю о событии «keydown», но это не то, что мне нужно. Через некоторое время ПОСЛЕ нажатия кнопки я хочу определить, нажата ли она по-прежнему.

P. S. Самая большая проблема заключается в том, что через некоторое время ключ начинает повторяться, вызывая события нажатия клавиш и нажатия клавиш, как злодей. Надеемся, что есть простая функция isKeyDown (key), но если нет, то эту проблему нужно будет преодолеть / обойти.

Ответы [ 12 ]

115 голосов
/ 16 января 2012

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

window.onmousemove = function (e) {
  if (!e) e = window.event;
  if (e.shiftKey) {/*shift is down*/}
  if (e.altKey) {/*alt is down*/}
  if (e.ctrlKey) {/*ctrl is down*/}
  if (e.metaKey) {/*cmd is down*/}
}

Это доступно для всех сгенерированных браузером объектов событий, таких как keydown, keyup и keypress, поэтому вам не нужно использовать mousemove.

Я пытался сгенерировать свои собственные объекты событий с document.createEvent('KeyboardEvent') и document.createEvent('KeyboardEvent') и искал e.shiftKey и тому подобное, но мне не повезло.

Я использую Chrome 17 на Mac

59 голосов
/ 01 декабря 2009

Есть ли способ определить, не активен ли ключ в JavaScript?

Нет. Единственная возможность - следить за каждым keyup и keydown и запоминать.

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

Так не должно быть. Вы обязательно получите keypress повторение, и во многих браузерах вы также получите повторение keydown, но если keyup повторяется, это ошибка.

К сожалению, это не совсем неслыханная ошибка: в Linux, Chromium и Firefox (когда он работает под GTK +, который находится в популярных дистрибутивах, таких как Ubuntu), оба генерируют повторяющиеся последовательности keyup-keypress-keydown удерживаемые ключи, которые невозможно отличить от кого-то, кто действительно быстро стучит по клавише.

35 голосов
/ 26 января 2016

Мое решение:

var keys = {};
window.onkeyup = function(e) { keys[e.keyCode] = false; }
window.onkeydown = function(e) { keys[e.keyCode] = true; }

Теперь я могу проверить, нажата ли какая-либо клавиша в другом месте скрипта, проверив

keys["code of the key"]

Если это правда, клавиша нажата.

11 голосов
/ 01 декабря 2009

Я не верю, что есть что-то вроде функции isKeyDown, но вы можете написать свою собственную.

По сути, создайте массив, длина которого равна количеству ключей, которые вы хотите отслеживать. Затем, используя события keyUp и keyDown для документов / страниц / элементов управления, обновите массив, указав состояние этого ключа.

Затем напишите функцию, которая проверяет, не нажата ли определенная клавиша, и возвращает bool.

var keyEnum = { W_Key:0, A_Key:1, S_Key:2, D_Key:3 };
var keyArray = new Array(4);

function onKeyDown()
{
    // Detect which key was pressed
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = true;
    // Repeat for each key you care about...
}

function onKeyUp()
{
    // Detect which key was released
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = false;
    // Repeat for each key you care about...
}

function isKeyDown(key)
{
    return keyArray[key];
}

Это должно выполнить то, что вы хотите.

1 голос
/ 12 февраля 2018

Завершено здесь, чтобы проверить, было ли что-то встроенное в браузер, но, похоже, его нет. Это мое решение (очень похоже на ответ Роберта):

"use strict";

let is_key_down = (() => {
    let state = {};

    window.addEventListener('keyup', (e) => state[e.key] = false);
    window.addEventListener('keydown', (e) => state[e.key] = true);

    return (key) => state.hasOwnProperty(key) && state[key] || false;
})();

Затем вы можете проверить, нажата ли клавиша, с помощью is_key_down('ArrowLeft').

1 голос
/ 25 августа 2015

Я использую следующий код:

var altKeyDownCount = 0;
window.onkeydown = function (e) {
    if (!e) e = window.event;
    if (e.altKey) {
        altKeyDownCount++;
        if (30 < altKeyDownCount) {
            $('.key').removeClass('hidden');
            altKeyDownCount = 0;
        }
        return false;
    }
}

window.onkeyup = function (e) {
    if (!e) e = window.event;
    altKeyDownCount = 0;
    $('.key').addClass('hidden');
}

Когда пользователь продолжает удерживать клавишу Alt в течение некоторого времени (около 2 секунд), появляется группа меток (class = 'key hidden'). Когда клавиша Alt отпускается, метки исчезают. Используются jQuery и Bootstrap.

1 голос
/ 11 марта 2014
/*
Tracks what keys are currently down on the keyboard
*/

function keyboard_module(onUpdate){
    var kb = {};
    var unicode_mapping = {};
    document.onkeydown = function(e){
        var unicode=e.charCode? e.charCode : e.keyCode
        var key = getKey(unicode);
        kb[key] = true;
        if(onUpdate){
            onUpdate(kb);
        }
    }

    document.onkeyup = function(e){
        var unicode=e.charCode? e.charCode : e.keyCode
        var key = getKey(unicode);
        delete kb[key];
        if(onUpdate){
            onUpdate(kb);
        }
    }

    function getKey(unicode){
        if(unicode_mapping[unicode]){
            var key = unicode_mapping[unicode];
        }else{
            var key= unicode_mapping[unicode] = String.fromCharCode(unicode);
        }
        return key;
    }
    return kb;
}

function testing(kb){
    console.log('These are the down keys', kb);
}


var keyboard = keyboard_module(testing);

....
//somewhere else in the code
if(keyboard['K']){/*do something special */}
1 голос
/ 01 декабря 2009

Другие люди уже задавали подобные вопросы раньше (хотя я не вижу здесь явных недоразумений).

Я думаю, что ответ в том, что событие keydown (и его близнец keyup) - это вся информация, которую вы получаете. Повторение достаточно прочно встроено в операционную систему, и прикладная программа не получает большой возможности запрашивать в BIOS фактическое состояние ключа.

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

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

0 голосов
/ 01 сентября 2018

Я отсканировал приведенные выше ответы, и предлагаемый keydown / keyup подход работает только при особых обстоятельствах. Если пользователь alt-tabs убирает или использует жест клавиши, чтобы открыть новое окно или вкладку браузера, тогда будет зарегистрирован keydown, что хорошо, потому что в этот момент невозможно определить, является ли ключ чем-то веб приложение отслеживает или является стандартным ярлыком браузера или операционной системы. Возвращаясь к странице браузера, он все равно будет думать, что ключ удерживается, хотя он был выпущен в то же время. Или какая-то клавиша просто удерживается, пока пользователь переключается на другую вкладку или приложение с помощью мыши, а затем отпускается за пределами нашей страницы.

Клавиши-модификаторы (Shift и т. Д.) Можно отслеживать с помощью mousemove и т. Д. При условии, что при переходе назад ожидается хотя бы одно взаимодействие с мышью, что часто имеет место.

Для большинства всех других клавиш (кроме модификаторов Tab, Delete, но включая Space, Enter) мониторинг keypress будет работать для большинства приложений - нажатая клавиша будет продолжать срабатывать. Однако существует некоторая задержка сброса ключа из-за периодичности срабатывания keypress. По сути, если keypress не продолжает стрелять, то можно исключить большинство ключей. Это в сочетании с модификаторами довольно герметично, хотя я не изучал, что делать с Tab и Backspace.

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

0 голосов
/ 08 января 2018

Я знаю, что это очень старый вопрос, однако есть очень легкая (~ .5Kb) библиотека JavaScript, которая эффективно «исправляет» непоследовательный запуск обработчиков событий клавиатуры при использовании DOM API.

Библиотека: Keydrown .

Вот пример рабочего кода, который хорошо сработал для моих целей, просто изменив ключ для установки слушателя:

kd.P.down(function () {
  console.log('The "P" key is being held down!');
});

kd.P.up(function () {
  console.clear();
});

// This update loop is the heartbeat of Keydrown
kd.run(function () {
  kd.tick();
});

Я включил Keydrown в свой клиентский JavaScript для правильной анимации паузы в игре Red Light Green Light, которую я пишу. Вы можете просмотреть всю игру здесь . (Примечание: если вы читаете это в будущем, игра должна быть завершена и играбельна :-D!)

Надеюсь, это поможет.

...