키가 다운되었는지 확인 하시겠습니까?


93

JavaScript에서 현재 키가 다운되었는지 감지하는 방법이 있습니까?

"keydown"이벤트에 대해 알고 있지만 그게 필요한 것은 아닙니다. 키를 누른 후 얼마 지나지 않아 여전히 눌려 있는지 감지하고 싶습니다.

추신 : 가장 큰 문제는 일정 시간이 지나면 키가 반복되기 시작하여 악마처럼 keydown 및 keyup 이벤트가 발생한다는 것입니다. 바라건대 단순한 isKeyDown (key) 함수가 있지만 그렇지 않다면이 문제를 극복하고 해결해야합니다.


6
여기에서 볼 수있는 답변의 일반적인 문제는 키를 누른 상태에서 탭을 변경하거나 포커스를 변경하고 키를 올린 다음 다시 전환하면 코드가 키를 다시 누르거나 이동할 때까지 키가 아래로 있다고 믿습니다. 페이지 위로 마우스를 이동합니다. :-(
Eric Mickelsen

답변:


73

JavaScript에서 현재 키가 다운되었는지 감지하는 방법이 있습니까?

아니. 유일한 가능성은 각각 모니터링 keyup하고 keydown그리고 기억.

일정 시간이 지나면 키가 반복되기 시작하여 악마처럼 keydown 및 keyup 이벤트를 발생시킵니다.

안됩니다. 당신은 확실히 keypress반복 될 것이고 , 많은 브라우저에서 당신은 또한 반복 될 것입니다 keydown. 그러나 keyup반복된다면 그것은 버그입니다.

불행히도 완전히 들어 본 적이없는 버그는 아닙니다. Linux, Chromium 및 Firefox (Ubuntu와 같은 인기있는 배포판에있는 GTK +에서 실행되는 경우)에서 둘 다 보유 키에 대해 반복되는 keyup-keypress-keydown 시퀀스를 생성합니다. 키를 정말 빨리 두드리는 사람과 구별 할 수 없습니다.


14
당신은 신사이자 학자입니다. Ubuntu의 Chromium과 Firefox는 내 기본 개발 환경이므로 내가보고있는 문제를 정확하게 설명합니다. 바라건대 더 나아질 것입니다. 그렇지 않으면 타이머 해킹 솔루션이 유일한 해결 방법 일 수 있습니다.
Daniel X Moore

3
네, 이것에 대한 진전이 없다는 것이 실망 스럽습니다. bugs.launchpad.net/ubuntu/+bug/369880을 참조 하세요 . 저는 브라우저 게임을 작성 중이며 현재 해결 방법은 전혀 반복되지 않는 수정 자 키 (shift, ctrl 등)를 사용하는 것입니다.
bobince

2
아니, 이다 대응 부족으로 정품 반복 키 누름 구별 할 수 keyup이벤트.
mako

4
8 년이 지난 지금도 그래요? 이 답변은 업데이트가 필요할 수 있습니다.
Marco Lavagnino

3
구문 분석 도움말 : (Linux && (Chromium || (Firefox && GTK +)))
bobince

134

사용하는 것 외에도 keyupkeydown핵심 다운 될 때 추적하고 백업하는 리스너가 있는 특정 키가 아래 경우에 당신에게 일부 속성은 실제로.

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등,하지만 난 운이 없었다.

Mac에서 Chrome 17을 사용하고 있습니다.


나는 새 브라우저와 이전 브라우저, 심지어 HTA에서도 이것을 사용하고 있습니다
Jakob Sternberg 2014 년

1
현재 일부 숫자가 다운되었을 때이 답변을 구현하는 방법이 있습니까? 나는 if (e.keyCode == 49) {console.log ( "1 is down");} 시도했지만 작동하지 않습니다. :(
Roberto Sepúlveda Bravo

안녕하세요 @ RobertoSepúlvedaBravo Robert가 다음 답변에서 질문에 답변하는 것 같습니다. ;)
Mark Odey 19 년

실제로 Shift를 의미하는 경우 keyup에서 e.shiftKey를 찾지 않아야합니다. 예를 들어 onclick에서 대신 e.shiftKey를 사용하십시오.
maciek

45

내 솔루션 :

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

이제 스크립트의 다른 곳에서 키를 눌렀는지 확인할 수 있습니다.

pressedKeys["code of the key"]

사실이면 키를 누릅니다.


2
키는 이미 함수이므로 다른 변수 이름이 더 좋을 수 있습니다.
Raven

1
Alt 키가 눌려 있는지 여부를 감지하는 데는 작동하지 않습니다.
Michael

1
이것은 최대 탐지를 위해 중대하다 / 하 / 좌 / 우
조나단 스 필러

11

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
이것은 훌륭하고 실제로 솔루션의 일부이지만 내가 경험하는 keyup 반복 버그를 해결하지 않습니다. bobince의 답변을 참조하십시오.
Daniel X Moore

4
점점 더 많은 ifs를 작성하는 것처럼 이것은 좋은 해결책이 아닙니다. "keyList = {};" 객체는 "keyList [key] = true;"를 허용합니다. 열거 형이나 제한없이 문자열 인덱스 / 속성을 사용하고 모든 키에 대해 작동합니다.
SparK

6

이미 브라우저에 내장 된 것이 있는지 확인하기 위해 여기까지 왔지만없는 것 같습니다. 이것은 내 솔루션입니다 (Robert의 대답과 매우 유사).

"use strict";

const is_key_down = (() => {
    const 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

다른 사람들은 전에 이런 종류의 질문을 한 적이 있습니다 (지금 당장은 명백한 속임수를 보지 못했지만).

대답은 keydown이벤트 (및 그 쌍둥이 keyup)가 여러분이 얻는 모든 정보라는 것입니다. 반복은 운영 체제에 매우 견고하게 연결되어 있으며 응용 프로그램은 BIOS에서 키의 실제 상태를 쿼리 할 기회를 많이 얻지 못합니다.

이 작업을 수행해야하는 경우 수행 할 수있는 작업은 키를 프로그래밍 방식으로 디 바운스하는 것입니다. 기본적으로, 당신은 평가할 수 keydownkeyup자신을하지만 무시 keyup이 지난 후 너무 빨리 일어나는 경우 이벤트를 keydown... 또는 본질적으로, 당신은 당신의 응답 지연한다 keyup확실히 또 다른이 아니다으로 긴만큼 keydown의 0.25 초 같은과 함께 다음과 같은 이벤트 keyup.

여기에는 타이머 활동을 사용하고 이전 이벤트에 대한 밀리 초 시간을 기록하는 것이 포함됩니다. 매우 매력적인 솔루션이라고는 말할 수 없지만 ...


2
이럴 까봐 걱정이되었습니다.
Daniel X Moore

1
/*
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 */}

확실하지 않은 경우 String.fromCharCode (unicode); 빠른 조회 여부이므로 unicode_mapping 개체가 있습니다. 이 코드가 초고속 인 경우이 코드를 약간 잘라 내야 할 수 있습니다. 키 다운에 대해 반복적으로 호출되므로 속도가 중요하므로 비관적으로 매핑을 추가했습니다.
RobKohr 2014 년

1

다음 코드는 내가 사용중인 코드입니다.

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이 모두 사용됩니다.


Alt 키를 누른 상태에서 "Tab"을 누르면 어떻게됩니까?
Michael

1

이것은 매우 오래된 질문이라는 것을 알고 있지만 DOM API를 사용할 때 키보드 이벤트 핸들러의 불일치 발생을 효과적으로 "패치"하는 매우 가벼운 (~ .5Kb) JavaScript 라이브러리가 있습니다.

라이브러리는 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();
});

내가 작성중인 Red Light Green Light 게임에서 적절한 일시 중지 애니메이션을 위해 Keydrown을 클라이언트 측 JavaScript에 통합했습니다. 여기 에서 전체 게임을 볼 수 있습니다 . (참고 : 나중에이 글을 읽는다면 게임은 코드가 완전하고 플레이 가능해야합니다. :-D!)

이게 도움이 되길 바란다.


1

위의 답변을 스캔했으며 제안 keydown/ keyup접근법은 특별한 상황에서만 작동합니다. 사용자가 Alt-Tab을 사용하지 않거나 키 제스처를 사용하여 새 브라우저 창 또는 탭을 열면 a keydown가 등록됩니다.이 시점에서 키가 웹 앱이 모니터링하는 항목인지 알 수 없기 때문에 괜찮습니다. , 또는 표준 브라우저 또는 OS 바로 가기입니다. 브라우저 페이지로 돌아 오면 키가 그동안 릴리스되었지만 여전히 키가 유지되었다고 생각할 것입니다. 또는 사용자가 마우스로 다른 탭이나 응용 프로그램으로 전환하는 동안 일부 키는 그대로 유지 된 다음 페이지 외부에서 해제됩니다.

뒤로 탭할 때 적어도 하나의 마우스 상호 작용이 예상된다는 가정하에 수정 자 키 Shift등을 모니터링 할 수 있습니다 mousemove.

다른 모든 키 대부분 (수정 제외 Tab, Delete하지만 포함 Space, Enter), 모니터링 keypress대부분의 응용 프로그램을 위해 일 것이다 - 주요 화재를 계속 누르고. 하지만 주기적으로 실행되기 때문에 키를 재설정하는 데 약간의 지연이 있습니다 keypress. 기본적으로 keypress계속 실행되지 않으면 대부분의 키를 배제 할 수 있습니다. 이것은 수정 자와 결합하여 매우 밀폐되어 있지만 Tab및으로 무엇을할지 탐구하지 않았습니다 Backspace.

이 DOM 약점을 추상화하는 라이브러리가 있거나 DOM 표준 변경이 다소 오래된 질문이기 때문에 처리 할 수있는 라이브러리가 있다고 확신합니다.


키 누르기는 이제 더 이상 사용되지 않습니다. Chrome에서 전혀 작동하지 않는 것 같습니다.
eadsjr

0

대답, 사용 onkeyuponkeydown. 이러한 이벤트에 대한 자세한 정보는 다음과 같습니다 .


1
인용 한 링크는 자동 반복이 문제가되지 않는 마우스 이벤트에 대한 것입니다.
Carl Smotricz 2009

key-up 및 key-down이 반복되지 않습니다. 키 누를 수도 있습니다.
Claudiu

글쎄 그들이 그렇게하더라도, 나는 TJMonk15의 해결책과 같은 것을 상상하고 있었다. 단지 그것을 작성하고 싶지 않았다
Claudiu

1
이 두 질문에 대한 표현은 정확히 동일합니다. 이상한 우연일까요 아니면 그 이상일까요?
Mitch Lindgren

2
@Mitch : 와우 ​​... 정말 대단하네요. 누군가가 같은 질문을하기 위해 두 개의 계정을 만드는 이유를 모르겠습니다. 또는 가능성이 사람은 다른 질문을 복사 키 위해 적응
Claudiu

0

이것은 Firefox와 Chrome에서 작동합니다.

Enter파일을 보거나 특수 온라인 편집기에서 편집하기 위해 특수 html 파일을 로컬로 열어야했습니다 ( Windows의 파일 탐색기에서 파일을 선택할 때 누름 ).

그래서 나는 키를 누른 상태에서 Ctrl키 를 누른 상태에서이 두 옵션을 구별하고 싶었습니다 Enter.

여기의 모든 답변에서 이해했듯이 이것은 실제로 가능하지 않은 것처럼 보이지만 여기에 저에게 허용되는 방식 으로이 행동을 모방하는 방법이 있습니다.

작동 방식은 다음과 같습니다.

Ctrl파일을 열 때 -key 를 누르고 있으면 자바 스크립트 코드에서 keydown 이벤트가 발생하지 않습니다. 그러나 keyup 이벤트가 발생합니다 (마지막으로 Ctrl-key를 놓을 때 ). 코드는 그것을 포착합니다.

이 코드는 키 이벤트 (키업 및 키 다운 모두)가 발생하는 즉시 해제합니다. 따라서 Ctrl파일이 열린 후-키 를 누르면 아무 일도 일어나지 않습니다.

window.onkeyup = up;
window.onkeydown = down;
function up(e) {
  if (e.key === 'F5') return; // if you want this to work also on reload with F5.

  window.onkeyup = null;
  window.onkeyup = null;
  if (e.key === 'Control') {
    alert('Control key was released. You must have held it down while opening the file, so we will now load the file into the editor.');
  }         
}
function down() {
  window.onkeyup = null;
  window.onkeyup = null;
}

-3
$('#mytextbox').keydown(function (e) {
            if (e.keyCode == 13) {
                if (e.altKey) {
                    alert("alt is pressed");
                }
            }
 });

Alt + Enter를 누르면 경고가 표시됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.