Periksa apakah ada kunci yang mati?

93

Adakah cara untuk mendeteksi jika kunci saat ini tidak aktif di JavaScript?

Saya tahu tentang acara "keydown", tapi bukan itu yang saya butuhkan. Beberapa saat SETELAH tombol ditekan, saya ingin dapat mendeteksi apakah masih ditekan.

PS Masalah terbesar tampaknya setelah beberapa periode waktu kunci mulai berulang, menembakkan keydown dan peristiwa keyup seperti iblis. Mudah-mudahan hanya ada fungsi isKeyDown (key) sederhana, tetapi jika tidak, masalah ini perlu diatasi / diatasi.

Daniel X Moore
sumber
6
Masalah umum dengan jawaban yang saya lihat di sini adalah jika Anda menahan tombol, lalu mengubah tab atau mengubah fokus, membiarkan kunci naik, dan kemudian beralih kembali, kode akan percaya bahwa tombol tersebut turun sampai Anda menekannya lagi atau memindahkan arahkan mouse ke atas halaman. :-(
Eric Mickelsen

Jawaban:

73

Adakah cara untuk mendeteksi jika kunci saat ini tidak aktif di JavaScript?

Nggak. Satu-satunya kemungkinan adalah memantau setiap keyupdan keydowndan mengingat.

setelah beberapa periode waktu kunci mulai berulang, menjalankan keydown dan event keyup seperti iblis.

Seharusnya tidak. Anda pasti akan keypressmengulang, dan di banyak browser Anda juga akan diulangi keydown, tetapi jika keyupberulang, itu bug.

Sayangnya ini bukan bug yang benar-benar tidak pernah terdengar: di Linux, Chromium, dan Firefox (saat dijalankan di bawah GTK +, yang ada di distro populer seperti Ubuntu) keduanya menghasilkan urutan keyup-keypress-keydown berulang untuk kunci yang ditahan, yang tidak mungkin dibedakan dari seseorang yang menekan kunci dengan sangat cepat.

bobince
sumber
14
Anda tuan adalah seorang pria dan seorang sarjana. Chromium dan Firefox di Ubuntu adalah lingkungan pengembangan utama saya, jadi itu menjelaskan masalah yang saya alami secara akurat. Semoga ini akan menjadi lebih baik, jika tidak, solusi peretasan pengatur waktu itu mungkin satu-satunya solusi.
Daniel X Moore
3
Ya, sangat mengesalkan karena tidak ada kemajuan dalam hal ini. Lihat bugs.launchpad.net/ubuntu/+bug/369880 . Saya sedang menulis game browser dan solusi saya untuk saat ini adalah tetap menggunakan tombol pengubah (shift, ctrl, dll.) Yang tidak berulang sama sekali.
bobince
2
Tidak, itu adalah mungkin untuk membedakan mereka dari tombol yang ditekan berulang asli dengan kurangnya sesuai keyupacara.
mako
4
apakah ini masih terjadi, 8 tahun kemudian? Jawaban ini mungkin perlu diperbarui.
Marco Lavagnino
3
bantuan parsing: (Linux && (Chromium || (Firefox && GTK +)))
sejak
134

Selain menggunakan keyupdan keydownpendengar untuk melacak kapan kunci turun dan cadangan, ada yang benar-benar beberapa sifat yang memberitahu Anda jika kunci tertentu turun.

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

Ini tersedia pada semua browser yang dihasilkan benda acara, seperti dari keydown, keyup, dan keypress, sehingga Anda tidak perlu menggunakan mousemove.

Saya mencoba membuat objek acara saya sendiri dengan document.createEvent('KeyboardEvent')dan document.createEvent('KeyboardEvent')dan mencari e.shiftKeydan semacamnya, tetapi saya tidak berhasil.

Saya menggunakan Chrome 17 di Mac

Devin G Rhode
sumber
Saya menggunakan ini, di peramban baru dan lama, bahkan HTA
Jakob Sternberg
1
Apakah ada cara untuk menerapkan jawaban ini ketika beberapa angka saat ini turun? Saya sudah mencoba dengan if (e.keyCode == 49) {console.log ("1 is down");} tetapi tidak berhasil :(
Roberto Sepúlveda Bravo
Hai @ RobertoSepúlvedaBravo Robert sepertinya menjawab pertanyaan Anda pada jawaban berikutnya. ;)
Mark Odey
Sebenarnya Anda tidak harus mencari e.shiftKey pada keyup jika yang Anda maksud adalah Shift. Gunakan e.shiftKey pada misalnya onclick.
maciek
46

Solusi saya:

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

Sekarang saya dapat memeriksa apakah ada tombol yang ditekan di tempat lain dalam skrip dengan memeriksa

pressedKeys["code of the key"]

Kalau benar, kuncinya ditekan.

Robert
sumber
2
Karena kunci sudah menjadi fungsi, nama variabel yang berbeda mungkin lebih baik.
Raven
1
ini tidak akan berfungsi untuk mendeteksi jika tombol Alt mati atau tidak di semua kasus.
Michael
1
Ini bagus untuk mendeteksi atas / bawah / kiri / kanan
Jonathan Spiller
11

Saya tidak percaya ada yang seperti fungsi isKeyDown, tetapi Anda bisa menulisnya sendiri.

Pada dasarnya, buat array yang panjangnya adalah jumlah kunci yang ingin Anda pantau. Kemudian menggunakan event documents / pages / kontrol keyUp dan keyDown, perbarui array dengan status kunci itu.

Kemudian tulis fungsi yang memeriksa apakah tombol tertentu tidak aktif dan mengembalikan 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];
}

Itu harus mencapai apa yang Anda inginkan.

FallenAvatar
sumber
1
Ini bagus, dan memang bagian dari solusi, tetapi tidak mengatasi bug pengulangan keyup yang saya alami. Lihat jawaban bobince.
Daniel X Moore
4
Ini bukan solusi yang baik karena Anda akan menulis lebih banyak jika. A "keyList = {};" menjadi objek menerima "keyList [key] = true;" tanpa memerlukan enum atau batas karena menggunakan indeks / properti string dan berfungsi untuk semua kunci.
SparK
6

Berakhir di sini untuk memeriksa apakah sudah ada sesuatu yang terpasang di browser, tetapi tampaknya tidak ada. Ini adalah solusi saya (sangat mirip dengan jawaban 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;
})();

Anda kemudian dapat memeriksa apakah ada tombol yang ditekan is_key_down('ArrowLeft').

antonagestam
sumber
1

Orang lain telah menanyakan pertanyaan semacam ini sebelumnya (meskipun saya tidak melihat ada penipuan yang jelas di sini sekarang).

Saya pikir jawabannya adalah bahwa keydownacara (dan kembarannya keyup) adalah semua info yang Anda dapatkan. Mengulangi terhubung dengan cukup kuat ke dalam sistem operasi, dan program aplikasi tidak mendapatkan banyak kesempatan untuk menanyakan BIOS untuk status kunci yang sebenarnya.

Apa yang dapat Anda lakukan, dan mungkin harus melakukannya jika Anda perlu membuatnya berfungsi, adalah dengan programmatic de-bounce key. Pada dasarnya, Anda dapat mengevaluasi keydowndan keyupdiri Anda sendiri tetapi mengabaikan suatu keyupperistiwa jika berlangsung terlalu cepat setelah yang terakhir keydown... atau pada dasarnya, Anda harus menunda tanggapan Anda keyupcukup lama untuk memastikan tidak ada keydownperistiwa lain yang mengikuti dengan sekitar 0,25 detik keyup.

Ini akan melibatkan penggunaan aktivitas pengatur waktu, dan mencatat waktu milidetik untuk peristiwa sebelumnya. Saya tidak bisa mengatakan itu solusi yang sangat menarik, tapi ...

Carl Smotricz
sumber
2
Saya khawatir hal itu akan terjadi.
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 */}
RobKohr
sumber
Tidak yakin apakah String.fromCharCode (unicode); adalah pencarian cepat atau tidak, jadi itulah mengapa saya memiliki objek unicode_mapping. Ini mungkin sesuatu yang menarik untuk memangkas kode ini sedikit jika sangat cepat. Karena ini akan dipanggil berulang kali untuk penurunan tombol, kecepatan itu penting, oleh karena itu saya menambahkan pemetaan dengan pesimis.
RobKohr
1

Kode berikut adalah yang saya gunakan:

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

Ketika pengguna terus menahan tombol Alt selama beberapa waktu (sekitar 2 detik), sekelompok label (class = 'key hidden') muncul. Saat tombol Alt dilepaskan, label menghilang. jQuery dan Bootstrap keduanya digunakan.

Johnny
sumber
dan apa yang terjadi jika "Tab" ditekan saat Alt turun?
Michael
1

Saya tahu ini pertanyaan yang sangat lama, namun ada pustaka JavaScript yang sangat ringan (~ .5Kb) yang secara efektif "menambal" pengaktifan penangan kejadian keyboard yang tidak konsisten saat menggunakan DOM API.

Perpustakaannya adalah Keydrown .

Berikut contoh kode operasi yang telah bekerja dengan baik untuk tujuan saya hanya dengan mengubah kunci untuk menyetel pendengar:

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

Saya telah memasukkan Keydrown ke JavaScript sisi klien saya untuk animasi jeda yang tepat dalam permainan Lampu Merah Hijau yang saya tulis. Anda dapat melihat keseluruhan game di sini . (Catatan: Jika Anda membaca ini di masa mendatang, kode game harus lengkap dan dapat dimainkan :-D!)

Saya harap ini membantu.

buildpax
sumber
1

Saya memindai jawaban di atas dan pendekatan keydown/ yang diusulkan keyuphanya berfungsi dalam keadaan khusus. Jika alt-tab pengguna menjauh, atau menggunakan isyarat tombol untuk membuka jendela atau tab browser baru, maka a keydownakan terdaftar, yang tidak masalah, karena pada saat itu tidak mungkin untuk mengetahui apakah kuncinya adalah sesuatu yang dipantau aplikasi web , atau browser standar atau pintasan OS. Kembali ke halaman browser, ia masih berpikir bahwa kunci tersebut ditahan, meskipun sementara itu dirilis. Atau beberapa kunci disimpan begitu saja, saat pengguna beralih ke tab atau aplikasi lain dengan mouse, lalu dilepaskan di luar halaman kami.

Tombol pengubah ( Shiftdll.) Dapat dipantau melalui mousemovedll. Dengan asumsi bahwa setidaknya ada satu interaksi mouse yang diharapkan saat melakukan tab ke belakang, yang sering terjadi.

Bagi kebanyakan semua kunci lainnya (kecuali pengubah, Tab, Delete, tapi termasuk Space, Enter), pemantauan keypressakan bekerja untuk sebagian besar aplikasi - kunci ditekan akan terus api. Ada beberapa latensi dalam menyetel ulang kunci, karena periodisitas keypresspenembakan. Pada dasarnya, jika keypresstidak terus aktif, maka mungkin saja untuk mengesampingkan sebagian besar kunci. Ini, dikombinasikan dengan pengubah cukup kedap udara, meskipun saya belum menjelajahi apa yang harus dilakukan dengan Tabdan Backspace.

Saya yakin ada beberapa perpustakaan di luar sana yang mengabstraksi kelemahan DOM ini, atau mungkin beberapa perubahan standar DOM menanganinya, karena ini pertanyaan yang agak lama.

Robert Monfera
sumber
penekanan tombol sekarang sudah tidak digunakan lagi. Sepertinya itu tidak berfungsi sama sekali di Chrome.
eadsjr
0

Lihat jawaban ini , dan gunakan onkeyupdan onkeydown. Berikut info yang lebih spesifik tentang acara tersebut.

Claudiu
sumber
1
Tautan yang Anda kutip adalah untuk peristiwa mouse, di mana pengulangan otomatis tidak menjadi masalah.
Carl Smotricz
key-up dan key-down tidak akan berulang. mungkin penekanan tombol.
Claudiu
baik bahkan jika mereka melakukannya, saya membayangkan sesuatu seperti solusi TJMonk15, hanya tidak ingin menulisnya
Claudiu
1
Kata-kata pada kedua pertanyaan itu persis sama. Kebetulan yang aneh, atau sesuatu yang lebih?
Mitch Lindgren
2
@ Mitch: wow ... itu sangat luar biasa. saya tidak tahu mengapa seseorang membuat dua akun untuk menanyakan pertanyaan yang sama. atau lebih mungkin orang ini hanya menyalin pertanyaan lain dan menyesuaikannya untuk kunci
Claudiu
0

Ini berfungsi di Firefox dan Chrome.

Saya memiliki kebutuhan untuk membuka file html khusus secara lokal (dengan menekan Entersaat file dipilih di file explorer di Windows), baik hanya untuk melihat file atau untuk mengeditnya di editor online khusus.

Jadi saya ingin membedakan antara dua opsi ini dengan menahan tombol- Ctrlatau tidak, sambil menekan Enter.

Seperti yang Anda semua pahami dari semua jawaban di sini, ini tampaknya tidak mungkin, tetapi berikut adalah cara yang meniru perilaku ini dengan cara yang dapat saya terima.

Cara kerjanya seperti ini:

Jika Anda menahan Ctrl-key saat membuka file maka peristiwa keydown tidak akan pernah aktif dalam kode javascript. Tapi peristiwa keyup akan aktif (saat Anda akhirnya melepaskan Ctrl-key). Kode menangkap itu.

Kode juga mematikan keyevents (baik keyup dan keydown) segera setelah salah satunya terjadi. Jadi jika Anda menekan Ctrl-key setelah file dibuka, tidak akan terjadi apa-apa.

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;
}
Magnus
sumber
-3
$('#mytextbox').keydown(function (e) {
            if (e.keyCode == 13) {
                if (e.altKey) {
                    alert("alt is pressed");
                }
            }
 });

jika Anda menekan alt + enter, Anda akan melihat peringatan.

Mokarom
sumber