キーが押されているかどうかを確認しますか?


91

JavaScriptで現在キーが押されているかどうかを検出する方法はありますか?

「keydown」イベントについては知っていますが、それは私が必要としていることではありません。キーが押された後、それがまだ押されているかどうかを検出できるようにしたいことがあります。

PS最大の問題は、しばらくしてからキーが繰り返され、悪魔のようなキーダウンイベントとキーアップイベントが発生することです。うまくいけば、単純なisKeyDown(key)関数があるだけですが、そうでない場合は、この問題を克服または回避する必要があります。


6
ここに表示される回答の一般的な問題は、キーを押したままタブを変更するか、フォーカスを変更し、キーを上にしてから元に戻すと、もう一度押すか移動するまで、キーが下にあるとコードが判断することです。ページ上にマウスを置きます。:-(
Eric Mickelsen

回答:


71

JavaScriptで現在キーが押されているかどうかを検出する方法はありますか?

いいえ。唯一の可能性は、それぞれkeyupを監視しkeydownて記憶することです。

しばらくすると、キーが繰り返され始め、フィーンドのようなキーダウンイベントとキーアップイベントが発生します。

すべきではない。あなたは間違いなくkeypress繰り返しを得るでしょう、そして多くのブラウザではあなたも繰り返されますkeydownが、keyup繰り返した場合、それはバグです。

残念ながら、これは完全に前代未聞のバグではありません。Linux、Chromium、Firefox(Ubuntuなどの一般的なディストリビューションでGTK +で実行されている場合)では、どちらも保持されたキーに対してkeyup-keypress-keydownシーケンスを繰り返し生成します。キーを非常に速く叩いている人と区別することは不可能です。


14
あなたは紳士で学者です。UbuntuでのChromiumとFirefoxは私の主要な開発環境です。そのため、私が今まで見てきた問題を正確に説明しています。うまくいけばそれは良くなるでしょう、さもなければそのタイマーハックソリューションが唯一の回避策かもしれません。
ダニエルXムーア

3
ええ、これに進展がないのはイライラします。bugs.launchpad.net/ubuntu/+bug/369880を参照してください。私はブラウザゲームを書いていて、当面の回避策は、まったく繰り返さない修飾キー(shift、ctrlなど)に固執することです。
ボビンス、2009

2
いいえ、対応するイベントがないことにより、真に繰り返されるキー入力と区別することできkeyupます。
mako 2014年

4
8年後の今もそうですか?この回答は更新が必要な場合があります。
Marco Lavagnino 2017年

3
ヘルプの解析:(Linux &&(Chromium ||(Firefox && GTK +)))
bobince

134

keyupkeydownリスナーを使用して、isキーのダウンとアップを追跡することに加えて、特定のキーがダウンしているかどうかを通知するプロパティ実際にいくつかあります。

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

これは、イベントなどからのものなどのオブジェクト、生成されたすべてのブラウザで利用可能であるkeydownkeyupとのkeypressあなたがのMouseMoveを使用する必要はありませんので、。

自分でイベントオブジェクトを生成しdocument.createEvent('KeyboardEvent')たりdocument.createEvent('KeyboardEvent')、探したりしてe.shiftKeyみましたが、うまくいきませんでした。

MacでChrome 17を使用しています


新しいブラウザと古いブラウザの両方で、HTAでもこれを使用しています
Jakob Sternberg

1
現在いくつかの数がダウンしているときにこの回答を実装する方法はありますか?{はconsole.log(「1がダウンしている」);}私は(e.keyCode == 49)場合にしようと試みましたが、機能していません:(
ロベルト・セプルベダブラボー

@RobertoSepúlvedaBravoRobertさん、次の回答であなたの質問に答えているようです。;)
Mark Odey

実際、Shiftを上回っている場合は、キーアップ時に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"]

trueの場合、キーが押されています。


2
keysはすでに関数であるため、別の変数名の方が良い場合があります。
レイヴン

1
これは、Altキーが押されているかどうかを検出する場合には機能しません。
マイケル

1
これは、上/下/左/右を検出するのに最適です
Jonathan Spiller

11

isKeyDown関数のようなものはないと思いますが、独自に作成することもできます。

基本的に、監視するキーの数を長さとする配列を作成します。次に、documents / pages / controlsのkeyUpイベントとkeyDownイベントを使用して、そのキーの状態で配列を更新します。

次に、特定のキーが押されているかどうかをチェックしてブール値を返す関数を記述します。

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
これは良いことであり、実際にソリューションの一部ですが、私が経験しているキーアップの繰り返しバグには対応していません。ボビンスの答えを見てください。
ダニエルXムーア

4
ifsをどんどん書くので、これは良い解決策ではありません。「keyList = {};」オブジェクトであることは「keyList [key] = true;」を受け入れます 文字列インデックス/プロパティを使用し、すべてのキーに対して機能するため、列挙型や制限は必要ありません。
SparK 2012

5

ブラウザーに何かが組み込まれているかどうかを確認するために、ここまでたどり着きましたが、そうではないようです。これは私の解決策です(ロバートの答えに非常に似ています):

"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わから別がありませんように十分な長さをkeydown0.25秒のようなもので、次のイベントkeyup

これには、タイマーアクティビティの使用と、以前のイベントのミリ秒の時間の記録が含まれます。非常に魅力的なソリューションとは言えませんが...


2
これになるのではないかと心配でした。
ダニエルXムーア

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」を押すとどうなりますか?
マイケル

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

Keydrownをクライアント側のJavaScriptに組み込んで、書いているRed Light Green Lightゲームの適切な一時停止アニメーションを作成しました。ここでゲーム全体を見ることができます。(注:将来これを読んでいる場合、ゲームはコードが完成し、プレイ可能である必要があります:-D!)

これがお役に立てば幸いです。


1

私は上記の回答をスキャンし、提案されたkeydown/ keyupアプローチは特別な状況でのみ機能します。ユーザーがalt-tabを離すか、キージェスチャーを使用して新しいブラウザーウィンドウまたはタブを開くと、keydownは登録されますが、その時点では、キーがWebアプリが監視しているものであるかどうかを判別できないため、問題ありません。 、または標準のブラウザまたはOSのショートカットです。ブラウザのページに戻ると、キーは保持されていると考えられますが、それまではリリースされていました。または、ユーザーがマウスを使って別のタブまたはアプリケーションに切り替えている間、いくつかのキーをそのまま保持したまま、ページの外にリリースします。

モディファイアキー(Shiftなど)はmousemove、タブバック時に予期される少なくとも1つのマウス操作があると想定して、などを介して監視できます。

他のすべてのキーほとんどの場合(修飾子を除き、TabDelete、しかし含むSpaceEnter)、モニタリングkeypressほとんどのアプリケーションのために働くだろう-キー、火災に続ける抑えました。ただし、起動の周期性により、キーのリセットには多少の遅延がありkeypressます。基本的に、keypress発砲し続けなければ、ほとんどのキーを除外することが可能です。私が何をすべきかを模索していないのに修飾と組み合わせるこれは、かなり気密性であるTabBackspace

これはかなり古い質問なので、このDOMの弱点を抽象化したライブラリがあるか、DOM標準の変更によって対処されたと思います。


keypressは非推奨になりました。Chromeではまったく動作しないようです。
eadsjr

0

この答えを見て、およびを使用onkeyupしてくださいonkeydown。これらのイベントに関するより具体的な情報を次に示します。


1
あなたが引用するリンクは、自動繰り返しが問題にならないマウスイベント用です。
Carl Smotricz、2009

キーアップとキーダウンは繰り返されません。キーを押す可能性があります。
Claudiu、

そうだとしても、私はTJMonk15のソリューションのようなものを想像していましたが、それを書きたくありませんでした
Claudiu

1
これら2つの質問の文言はまったく同じです。奇妙な偶然、またはそれ以上?
ミッチリンドグレン

2
@ミッチ:すごい...それはかなり素晴らしいです。なぜ誰かが同じ質問をするために2つのアカウントを作成するのかわかりません。あるいは、おそらくこの人は他の質問をコピーしてキーに合わせました
Claudiu

0

これはFirefoxとChromeで動作します。

Enterファイルを表示するため、または特別なオンラインエディターで編集するために、特別なhtmlファイルをローカルで開く(Windowsのファイルエクスプローラーでファイルを選択するときに押す)必要がありました。

ですからCtrl、を押しながら-キーを押すかどうかにかかわらず、これら2つのオプションを区別したいと思いましたEnter

ここでのすべての答えから理解しているように、これは実際には可能ではないようですが、ここでは、この動作を私に受け入れられる方法で模倣しています。

これが機能する方法は次のとおりです。

Ctrlファイルを開くときに-key を押したままにすると、JavaScriptコードでkeydownイベントが発生することはありません。しかし、キーアップイベントが発生します(最終的に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.