回答:
注: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つ以上のキーを一度にチェックできます。
説明のために、あなたがAand を押すとB、それぞれがtrueまたはfalseに評価されるの値にkeydown
設定するイベントを起動するとします。これで両方とに設定されました。を離すと、イベントが発生し、同じロジックで(A)の反対の結果を決定します。これは現在falseですが、(B)はまだ「ダウン」しているため(キーアップイベントはトリガーされていません)、それは本当のままです。map[e.keyCode]
e.type == keydown
map[65]
map[66]
true
A
keyup
map[65]
map[66]
map
配列は、両方のイベントを通じて、次のようになります。
// keydown A
// keydown B
[
65:true,
66:true
]
// keyup A
// keydown B
[
65:false,
66:true
]
今できることは2つあります。
A)キーロガー(例)は、後で1つ以上のキーコードをすばやく把握したい場合に参照として作成できます。あなたが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>
これにより、JavaScriptで簡単に参照できるHTML要素が作成されます。 element
alert(element); // [Object HTMLDivElement]
あなたはそれを使用しdocument.getElementById()
たり$()
つかんだりする必要さえありません。ただし、互換性のために、jQueryを使用することを$()
お勧めします。
スクリプトタグがHTMLの本文の後に来るようにしてください。最適化のヒント:ほとんどの有名なWebサイトでは、最適化のためにbodyタグの後に scriptタグを配置しています。これは、scriptタグが、スクリプトのダウンロードが完了するまで、それ以上の要素の読み込みをブロックするためです。コンテンツの前に置くと、コンテンツを事前に読み込むことができます。
B(興味のある場所)一度に1つ以上のキーを確認でき/*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');
}
}
(編集終了)
この例のチェックのためにCtrlShiftA、CtrlShiftBと、CtrlShiftC
それはそれと同じくらい簡単です:)
一般的な規則として、コード、特にキーコード(など // CTRL+ENTER
)を文書化して、それらが何であったかを思い出せるようにすることをお勧めします。
また、ドキュメントと同じ順序でキーコードを配置する必要があります(CTRL+ENTER => map[17] && map[13]
、NOT map[13] && map[17]
)。このようにして、コードに戻って編集する必要があるときに混乱することはありません。
異なる量のコンボ(CtrlShiftAltEnterやなどCtrlEnter)をチェックする場合は、大きいコンボの後に小さいコンボを配置するか、小さいコンボが十分に類似している場合は、大きいコンボをオーバーライドします。例:
// 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
ここに私が見つけた迷惑なものがあります、解決策が含まれています:
問題:ブラウザーは通常CtrlD、CtrlShiftCキーコンボでデフォルトのアクション(ブックマークウィンドウをアクティブにする、またはmaxthonでスカイノートをアクティブにするなど)を持っているため、のreturn false
後に追加することもできますmap = []
。これにより、「ファイルの複製」時にサイトのユーザーが不満を感じないようになります。関数がに置かれCtrlD、代わりにページをブックマークします。
if(map[17] && map[68]){ // CTRL+D
alert('The bookmark window didn\'t pop up!');
map = {};
return false;
}
がなければreturn false
、ブックマークウィンドウがポップアップし、ユーザーをがっかりさせます。
わかりましたので、その時点で関数を常に終了する必要はありません。それがevent.preventDefault()
関数が存在する理由です。それが行うことは、ブラウザにデフォルトのアクションを実行させないようにインタープリタに指示する内部フラグを設定することです。その後、関数の実行が続行されます(関数return
はすぐに終了します)。
あなたが使用するかどうかを決定する前にこの区別を理解しますreturn false
かe.preventDefault()
event.keyCode
廃止されましたユーザーSeanVieiraevent.keyCode
は、非推奨となったコメントで指摘しました。
そこで、彼は優れた代替手段を提供しました:はevent.key
、"a"
for Aや"Shift"
forのように、押されているキーの文字列表現を返します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
方が記述しやすく、理由付けも簡単です。
attachEvent("onevent", callback)
Internet Explorerの非標準実装からのものもありますが、これは非推奨ではなく、JavaScriptにも関係しません(JScriptと呼ばれる難解な言語に関係します)。ポリグロットコードをできるだけ回避することをお勧めします。
混乱/苦情に対処するために、この抽象化を行う「クラス」を作成しました(pastebin link):
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
(textareaであると想定して)接続され、キーcomboのウォッチポイントが設定されますCtrl+5
。ときに両方Ctrl
と5
ダウンしている、あなたが渡されたコールバック関数(この場合には、追加機能"FIVE "
テキストエリアには)と呼ばれます。コールバックはname print_5
に関連付けられているので、それを削除するには、次のように使用します。
input_txt.unwatch("print_5");
要素input_txt
から切り離すにはtxt
:
input_txt.detach();
このようにして、ガベージコレクションはオブジェクト(input_txt
)を取得できます。オブジェクトが破棄された場合、古いゾンビイベントリスナーが残ってしまうことはありません。
完全を期すために、C / Javaスタイルで提示されたクラスのAPIのクイックリファレンスを以下に示します。これにより、クラスが返すものと期待する引数がわかります。
Boolean key_down (String key);
ダウンしている
true
場合key
はfalseを返し、それ以外の場合は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 = {}
上記と同等void detach (void);
ev_kdown
とev_kup
リスナーを親要素から切り離し、インスタンスを安全に削除できるようにします
更新2017-12-02これをgithubに公開するリクエストに応えて、要旨を作成しました。
更新2018-07-21私はしばらく宣言型スタイルのプログラミングを行ってきましたが、これが今では私の個人的なお気に入りです:fiddle、pastebin
一般的には、現実的に必要なケース(Ctrl、Alt、Shift)で機能しますが、たとえば、a+w
同時にヒットする必要がある場合は、アプローチを "組み合わせて"マルチキールックアップ。
これが完全に説明された回答のミニブログが役に立てば幸いです:)
return false
vspreventDefault()
keyCode
廃止予定です-に切り替えるとkey
、キーの実際の文字表現が得られます。
myString[5]
同じで5[myString]
、コンパイルの警告が表示されないことを知っていますか(を使用しても-Wall -pedantic
)?これは、pointer[offset]
表記がポインタを受け取り、オフセットを追加し、結果を逆参照しmyString[5]
てと同じにするため*(myString + 5)
です。
あなたは使用する必要があるのkeydown押されたキーを追跡するためのイベントを、そしてあなたが使用する必要がありますからkeyupキーがリリースされたときを追跡するためのイベントを。
この例を参照してください: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を使用して物事を簡単に行えるようにしましたが、この概念は「生の」JavaScriptで作業する場合にも機能します。
onblur
、押されたすべてのキーを配列から削除するイベントハンドラーを追加することもできます。フォーカスを失ったら、すべてのキーをもう一度押す必要があります。残念ながら、に相当するJSはありませんGetKeyboardState
。
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;
}
});
完全なサンプルコードが必要な人のために。右+左が追加されました
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);
keydownが複数の関数を呼び出すようにし、各関数が特定のキーをチェックして適切に応答するようにします。
document.keydown = function (key) {
checkKey("x");
checkKey("y");
};
にkeypress
Event
ハンドラーを追加してみますkeydown
。例えば:
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
登録については触れません)。
これが役立つかどうかを投稿してください。
押されたキーの1つが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()
}
}
}
$(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;
}
});
});
これは普遍的な方法ではありませんが、場合によっては便利です。CTRL+ somethingまたはShift+ somethingまたはCTRL+ Shift+ somethingなどの組み合わせに役立ちます。
例:CTRL+ を使用してページを印刷する場合P、最初に押されたキーのCTRL後には常にが続きPます。CTRL+ S、CTRL+ Uおよび他の組み合わせと同じです。
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;
}
}
});
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);