programing

JavaScript를 사용하여 여러 키를 동시에 눌렀는지 어떻게 검출합니까?

minecode 2022. 9. 22. 21:17
반응형

JavaScript를 사용하여 여러 키를 동시에 눌렀는지 어떻게 검출합니까?

JavaScript 게임 엔진을 개발하려고 하는데 이 문제를 발견했습니다.

  • 내가 누르면 캐릭터가 점프해.
  • 누르면 캐릭터가 오른쪽으로 이동합니다.

문제는 오른쪽을 누른 후 공간을 누르면 캐릭터가 점프하여 움직임을 멈춘다는 것입니다.

용 the the the를 .keydown키를 누르는 기능을 수행합니다.한 번에 여러 개의 키가 눌려 있는지 확인하려면 어떻게 해야 하나요?

주의: keyCode는 폐지되었습니다.

개념을 이해하면 여러 키 입력 검출이 용이합니다.

제가 하는 방법은 다음과 같습니다.

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

이 코드는 매우 간단합니다.컴퓨터는 한 번에 하나의 키 입력만 통과하므로 여러 키를 추적하기 위해 배열이 생성됩니다.그런 다음 어레이를 사용하여 한 번에 하나 이상의 키를 확인할 수 있습니다.

설명하자면, 를 누른다고 가정해 보겠습니다.각각은 1초당 1초당 1초당 1초당 1초씩keydown를 설정하는 map[e.keyCode]e.type == keydowntrue 또는 false 중 하나로 평가됩니다.이제 둘 다map[65] ★★★★★★★★★★★★★★★★★」map[66]로 설정되어 있다.true ★★★★★★★★★★★★★★★★★★★★★★를 놓으면,A , . . . . . . . .keyup에서는, 이 「이벤트 기동」에 반대의 를 판별합니다.map[65](A) 지금은 거짓이지만,map[66](B)는 여전히 "down"(키업 이벤트를 트리거하지 않음)이며 true로 유지됩니다.

map 현상을 다음과.

// 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>

참조할 수 됩니다.element

alert(element); // [Object HTMLDivElement]

.document.getElementById() ★★★★★★★★★★★★★★★★★」$()jQuery를 사용합니다.$()보다 폭넓게 권장됩니다.

스크립트 태그가 HTML 본문 뒤에 있는지 확인하세요.최적화 힌트:대부분의 유명 웹사이트는 최적화를 위해 본문 태그 뒤에 스크립트 태그를 붙입니다.스크립트 태그는 스크립트 다운로드가 완료될 때까지 추가 요소의 로드를 차단하기 때문입니다.컨텐츠보다 앞에 두면, 컨텐츠를 사전에 로드할 수 있습니다.

B(관심이 있는 위치) 한 번에 하나 이상의 키를 확인할 수 있습니다./*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');
}

편집: 가장 읽기 쉬운 토막이 아닙니다.가독성이 중요하기 때문에 다음과 같은 기능을 사용하여 쉽게 볼 수 있습니다.

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+ENTER)을(를) 기억하실 수 있습니다.

.CTRL+ENTER => map[17] && map[13].map[13] && map[17]이렇게 하면 코드를 다시 편집해야 할 때 혼란이 생기지 않습니다.

if-else 체인이 달린 gotcha

다른 양의 콤보(및 등)를 체크할 경우 큰 콤보 뒤에 작은 콤보를 넣습니다.그렇지 않으면 작은 콤보가 큰 콤보보다 우선합니다.예:

// 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"

Gotcha: "키를 누르지 않아도 이 키 조합이 계속 활성화됩니다."

메인창에서 는 '경보'나 '경보'를 할 수 .map = []이치노왜냐하면 어떤 일들은...alert()기본 창에서 포커스를 떼고 '키업' 이벤트가 트리거되지 않도록 합니다.예를 들어 다음과 같습니다.

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

Gotcha: 브라우저 기본값

다음은 솔루션과 함께 발견한 성가신 내용입니다.

문제:브라우저에는 보통 키 조합에 대한 기본 작업(북마크 창 활성화 또는 maxthon에서 skynote 활성화 등)이 있으므로 추가하기를 원할 수도 있습니다.return false 후에map = []따라서 사이트 사용자는 "Duplicate File(파일 복제)" 기능을 on으로 하여 페이지를 북마크해도 당황하지 않습니다.

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

return false[ Bookmark ](북마크)이 팝업 되어 사용자를 실망시킵니다.

반품명세서(신규)

그 시점에서 항상 기능을 종료하고 싶은 것은 아닙니다.그 that가event.preventDefault()기능이 있습니다.브라우저가 기본 액션을 실행하지 않도록 인터프리터에 지시하는 내부 플래그를 설정합니다.그 후 함수의 실행은 계속됩니다(여기에 따라).return을 이용하다

한 후 사용 하십시오.return false ★★★★★★★★★★★★★★★★★」e.preventDefault()

event.keyCode되지 않습니다.

사용자 SeanVieira는 댓글에서 다음과 같이 지적했다.event.keyCode을 사용하다

했습니다: 거기, ,, there there there there there there there there there there there there there there there there there there there there there 。event.key 키의 문자열 를 들어, 「키」는 「키」는 「키」입니다."a"의 경우"Shift"용으로 설정합니다.

나는 그 현을 검사하기 위한 도구를 만들어 냈다.

element.onevent »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더더 、 론론론론론것 。

, there있있 there 도 있다.attachEvent("onevent", callback)그러나 이는 폐지된 것을 넘어 자바스크립트(JScript라고 하는 난해한 언어와 관련되지도 않습니다).가능한 한 폴리글롯 코드를 사용하지 않는 것이 가장 좋습니다.

도우미 클래스

혼란/불만에 대처하기 위해 다음 추상화(pastebin 링크)를 수행하는 "클래스"를 작성했습니다.

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★★★★

input_txt.detach();

하면 가비지 컬렉션」)를 할 수 .input_txt버리면 오래된 좀비 이벤트 청취자가 남지 않습니다.

C/Java 스타일로 제공되는 클래스의 API에 대한 간단한 참조를 통해 반환되는 항목과 예상되는 인수를 알 수 있습니다.

Boolean  key_down (String key);

truekey거짓

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

true 키를 누르면key1 .. keyN거짓

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

'감시 포인트'를 포인트.keyN.

void     unwatch (String name);

해당 이름을 사용하여 해당 감시점을 제거합니다.

void     clear (void);

「키 다운」캐시를 소거합니다.가가에 map = {}

void     detach (void);

.ev_kdown ★★★★★★★★★★★★★★★★★」ev_kup할 수 .

업데이트 2017-12-02 GITHUB에 게시해달라는 요청에 따라 GIST를 작성하였습니다.

업데이트 2018-07-21 한동안 선언형 프로그래밍을 사용했는데, 지금은 이 방법이 제가 개인적으로 가장 좋아하는 방법입니다: findle, pastebin

경우 shift)와함께 할 수 , , alt, shift)를 쳐야 ctrl, alt, shift를 쳐야 할 에는 ctrl, alt, shift를 합니다.a+w동시에 접근 방식을 다중 키 모음으로 "수정"하는 것은 그리 어렵지 않습니다.


답변 미니 블로그가 도움이 되었기를 바랍니다:)

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");

    } 

}

다운 이벤트를 사용하여 누른 키를 추적하고 키 이벤트를 사용하여 키가 언제 해제되었는지 추적해야 합니다.

다음의 예를 참조해 주세요.http://jsfiddle.net/vor0nwe/mkHsU/

(갱신:jsfiddle.net가 실패할 경우를 대비해서 여기서 코드를 재생하고 있습니다.HTML:

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

...그리고 Javascript(jQuery 사용):

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를 사용하여 작업을 쉽게 수행했지만, 이 개념은 'raw' Javascript에서 작업할 때도 동일하게 작동합니다.

완전한 예제 코드가 필요한 사용자를 위해.오른쪽+왼쪽 추가

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);

이 방법을 사용했습니다(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.addEventListener('keydown',function(e){
      
    //SHIFT + something
    if(e.shiftKey){
        switch(e.code){

            case 'KeyS':
                console.log('Shift + S');
                break;

        }
    }

    //CTRL + SHIFT + something
    if(e.ctrlKey && e.shiftKey){
        switch(e.code){

            case 'KeyS':
                console.log('CTRL + Shift + S');
                break;

        }
    }

});

게임 입력 스크립트를 작성할 때 매우 유용한 스니펫을 사용하고 싶습니다.

var keyMap = [];

window.addEventListener('keydown', (e)=>{
    if(!keyMap.includes(e.keyCode)){
        keyMap.push(e.keyCode);
    }
})

window.addEventListener('keyup', (e)=>{
    if(keyMap.includes(e.keyCode)){
        keyMap.splice(keyMap.indexOf(e.keyCode), 1);
    }
})

function key(x){
    return (keyMap.includes(x));
}

function checkGameKeys(){
    if(key(32)){
        // Space Key
    }
    if(key(37)){
        // Left Arrow Key
    }
    if(key(39)){
        // Right Arrow Key
    }
    if(key(38)){
        // Up Arrow Key
    }
    if(key(40)){
        // Down Arrow Key
    }
    if(key(65)){
        // A Key
    }
    if(key(68)){
        // D Key
    }
    if(key(87)){
        // W Key
    }
    if(key(83)){
        // S Key
    }
}

각 기능이 특정 키를 확인하고 적절하게 응답하는 여러 함수를 호출하는 키다운을 만듭니다.

document.keydown = function (key) {

    checkKey("x");
    checkKey("y");
};
    $(document).ready(function () {
        // using ascii 17 for ctrl, 18 for alt and 83 for "S"
        // ctr+alt+S
        var map = { 17: false, 18: false, 83: false };
        $(document).keyup(function (e) {
            if (e.keyCode in map) {
                map[e.keyCode] = true;
                if (map[17] && map[18] && map[83]) {
                    // Write your own code here, what  you want to do
                    map[17] = false;
                    map[18] = false;
                    map[83] = false;
                }
            }
            else {
                // if u press any other key apart from that "map" will reset.
                map[17] = false;
                map[18] = false;
                map[83] = false;
            }
        });

    });

여기 브래든스의 답변이 있습니다.

var keys = {}
function handleKeyPress(evt) {
  let { keyCode, type } = evt || Event; // to deal with IE
  let isKeyDown = (type == 'keydown');
  keys[keyCode] = isKeyDown;

  // test: enter key is pressed down & shift isn't currently being pressed down 
  if(isKeyDown && keys[13] && !keys[16]){
    console.log('user pressed enter without shift')
  }
};

window.addEventListener("keyup", handleKeyPress);
window.addEventListener("keydown", handleKeyPress);

저도 한번 keypress Eventkeydown

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+는 ).여기서는 자세히 설명하지 않겠습니다(특히 브라우저 고유의 레벨 2+는 설명하지 않습니다).Event★★★★★★★★★★★★★★★★★★」

도움이 되든 안 되든 다시 올려주세요.

누른 키 중 하나가 Alt / Crtl / Shift인 경우 다음 방법을 사용할 수 있습니다.

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()
    }
  }
}
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;

최선의 방법은 아닌 거 알아.

좀 더 안정적인 것을 만드는 것 뿐:

var keys = [];
$(document).keydown(function (e) { 
    if(e.which == 32 || e.which == 70){
    keys.push(e.which);
    if(keys.length == 2 && keys.indexOf(32) != -1 && keys.indexOf(70) != -1){
        
        
        
        alert("it WORKS !!"); //MAKE SOMETHING HERE---------------->
        
        
        
        keys.length = 0;
    }else if((keys.indexOf(32) == -1 && keys.indexOf(70) != -1) || (keys.indexOf(32) != -1 && keys.indexOf(70) == -1) && (keys.indexOf(32) > 1 || keys.indexOf(70) > 1)){
    }else{
        keys.length = 0;
    }
}else{
    keys.length = 0;
}
});

컨트롤 키로 키 누르기 이벤트를 찾으려면 다음과 같이 하십시오.

onkeypress = (e) =>{
console.log(e);
if(e.ctrlKey && e.code == "KeyZ"){
    document.write("do somthing")
} }
Easiest, and most Effective Method

//check key press
    function loop(){
        //>>key<< can be any string representing a letter eg: "a", "b", "ctrl",
        if(map[*key*]==true){
         //do something
        }
        //multiple keys
        if(map["x"]==true&&map["ctrl"]==true){
         console.log("x, and ctrl are being held down together")
        }
    }

//>>>variable which will hold all key information<<
    var map={}

//Key Event Listeners
    window.addEventListener("keydown", btnd, true);
    window.addEventListener("keyup", btnu, true);

    //Handle button down
      function btnd(e) {
      map[e.key] = true;
      }

    //Handle Button up
      function btnu(e) {
      map[e.key] = false;
      }

//>>>If you want to see the state of every Key on the Keybaord<<<
    setInterval(() => {
                for (var x in map) {
                    log += "|" + x + "=" + map[x];
                }
                console.log(log);
                log = "";
            }, 300);

언급URL : https://stackoverflow.com/questions/5203407/how-to-detect-if-multiple-keys-are-pressed-at-once-using-javascript

반응형