Anahtarın çalışmadığını kontrol edin.


94

Şu anda JavaScript'te bir anahtarın çalışmadığını tespit etmenin bir yolu var mı?

"Keydown" olayını biliyorum, ama ihtiyacım olan bu değil. Tuşa basıldıktan bir süre sonra, hala basılı olup olmadığını tespit edebilmek istiyorum.

Not: En büyük sorun, bir süre sonra anahtarın tekrar etmeye başlaması, bir şeytan gibi keydown ve keyup olaylarını kapatması gibi görünüyor. Umarım basit bir isKeyDown (anahtar) işlevi vardır, ancak değilse bu sorunun üstesinden gelinmesi / üzerinde çalışılması gerekecektir.


6
Burada gördüğüm yanıtlarla ilgili yaygın bir sorun, bir tuşu basılı tutup sekmeleri değiştirirseniz veya odağı değiştirirseniz, tuşun yukarı çıkmasına izin verirseniz ve sonra geri dönerseniz, kodun siz tuşa tekrar basana veya hareket edene kadar tuşun aşağıda olduğuna inanacağıdır. fareyi sayfanın üzerine getirin. :-(
Eric Mickelsen

Yanıtlar:


74

Şu anda JavaScript'te bir anahtarın çalışmadığını tespit etmenin bir yolu var mı?

Hayır! Tek olasılık her izlemektedir keyupve keydownve hatırlama.

bir süre sonra anahtar tekrar etmeye başlar, bir şeytan gibi keydown ve keyup olaylarını kapatır.

Yapmamalı. Kesinlikle keypresstekrar edeceksiniz ve birçok tarayıcıda da tekrarlanacaksınız keydown, ancak keyuptekrarlarsa, bu bir hata.

Ne yazık ki bu tamamen duyulmamış bir hata değil: Linux, Chromium ve Firefox'ta (Ubuntu gibi popüler dağıtımlarda bulunan GTK + altında çalıştırıldığında) her ikisi de tutulan tuşlar için tekrar eden tuş-tuş basma-tuş düşürme dizileri üretir, Bu, anahtarı gerçekten hızlı vuran birinden ayırt etmek imkansızdır.


14
Beyefendi ve bilginsiniz. Ubuntu'daki Chromium ve Firefox benim birincil geliştirme ortamım, bu yüzden karşılaştığım sorunu doğru bir şekilde açıklıyor. Umarım daha iyi hale gelir, aksi takdirde bu zamanlayıcı hack çözümü tek geçici çözüm olabilir.
Daniel X Moore

3
Evet, bu konuda ilerleme olmaması sinir bozucu. Bugs.launchpad.net/ubuntu/+bug/369880 adresine bakın . Bir tarayıcı oyunu yazıyorum ve şu an için çözümüm, hiç tekrar etmeyen değiştirici tuşlara (shift, ctrl vb.) Bağlı kalmak.
bobince

2
Hayır, olduğu tekabül onların eksikliği hakiki tekrarlanan basılmasını ayırt etmek mümkün keyupolaylar.
mako

4
8 yıl sonra durum hala böyle mi? Bu cevabın güncellenmesi gerekebilir.
Marco Lavagnino

3
ayrıştırma yardımı: (Linux && (Chromium || (Firefox && GTK +)))
bobince

134

Tuşun ne zaman aşağı inip çıktığını izlemek için dinleyiciler kullanmaya keyupve keydowndinleyicilere ek olarak , aslında size belirli tuşların kapalı olup olmadığını söyleyen bazı özellikler vardır.

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

Bu tür gelenler gibi tüm tarayıcı oluşturulan olay nesneleri mevcuttur keydown, keyupve keypresssen kullanımı mouseMove zorunda kalmamak.

Kendi olay nesnelerimi document.createEvent('KeyboardEvent')ve ile oluşturmaya çalıştım document.createEvent('KeyboardEvent')ve aradım e.shiftKey, ama hiç şansım olmadı.

Mac'te Chrome 17 kullanıyorum


Bunu hem yeni hem de eski tarayıcılarda, hatta HTA'larda kullanıyorum
Jakob Sternberg

1
Şu anda bazı rakamlar azaldığında bu cevabı uygulamanın bir yolu var mı? İf (e.keyCode == 49) {console.log ("1 is down");} ile denedim ama çalışmıyor :(
Roberto Sepúlveda Bravo

Hey @ RobertoSepúlvedaBravo Robert, sorunuzu bir sonraki yanıtta yanıtlıyor gibi görünüyor. ;)
Mark Odey

Aslında Shift'den bahsediyorsanız, keyup'ta e.shiftKey'i aramamalısınız. Bunun yerine e.shiftKey'i örneğin onclick'te kullanın.
maciek

46

Çözümüm:

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

Şimdi komut dosyasının herhangi bir yerinde herhangi bir tuşa basılıp basılmadığını kontrol edebilirim.

pressedKeys["code of the key"]

Doğruysa, tuşuna basılır.


2
Anahtarlar zaten bir işlev olduğundan, farklı bir değişken adı daha iyi olabilir.
Raven

1
bu, her durumda Alt tuşunun aşağıda olup olmadığını tespit etmek için çalışmayacaktır.
Michael

1
Bu, yukarı / aşağı / sol / sağı algılamak için harika
Jonathan Spiller

11

İsKeyDown işlevi gibi bir şey olduğuna inanmıyorum, ancak kendiniz yazabilirsiniz.

Temel olarak, uzunluğu izlemek istediğiniz anahtar sayısı olan bir dizi oluşturun. Ardından, belgeler / sayfalar / kontroller keyUp ve keyDown olaylarını kullanarak, diziyi bu anahtarın durumuyla güncelleyin.

Ardından belirli bir tuşun kapalı olup olmadığını kontrol eden ve bir bool döndüren bir işlev yazın.

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];
}

Bu, istediğinizi başarmalıdır.


1
Bu iyi ve gerçekten de çözümün bir parçası, ancak karşılaştığım keyup yineleme hatasını ele almıyor. Bobince'nin cevabına bakın.
Daniel X Moore

5
Gittikçe daha fazla ifs yazacağınız için bu iyi bir çözüm değil. Bir "keyList = {};" nesne olmak "keyList [key] = true" kabul eder; dize dizinlerini / özelliklerini kullandığından ve tüm anahtarlar için çalıştığından bir numaralandırmaya veya sınırlamaya gerek yoktur.
SparK

Bu işe yarıyor ama fazlasıyla tasarlanmış
scitronboy

6

Tarayıcıda zaten yerleşik bir şey olup olmadığını kontrol etmek için burada sona erdi, ancak yok gibi görünüyor. Bu benim çözümüm (Robert'ın cevabına çok benzer):

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

Daha sonra ile bir tuşa basılıp basılmadığını kontrol edebilirsiniz is_key_down('ArrowLeft').


1

Başkaları bu tür bir soruyu daha önce sordular (gerçi şu anda burada bariz ikilemler görmüyorum).

Bence cevabın, keydownolayın (ve keyupikisinin) aldığınız tüm bilgiler olması. Tekrarlama, işletim sistemine oldukça sıkı bir şekilde bağlanmıştır ve bir uygulama programı, anahtarın gerçek durumu için BIOS'u sorgulama fırsatına sahip değildir.

Yapabileceğiniz ve belki de bunu çalıştırmanız gerekiyorsa yapmanız gereken şey, programlı olarak anahtarı geri döndürmektir. Esasen, değerlendirebilir keydownve keyupkendinizi ancak görmezden keyupson sonra çok hızlı bir şekilde gerçekleşmesi durumunda olayı keydown... ya esasen, sen verdiğintepkileri ertelemesi gerekir keyupemin başka bir şey yok olmaya yeterince uzun keydown0,25 saniye gibi bir şey ile aşağıdaki olay keyup.

Bu, bir zamanlayıcı etkinliği kullanmayı ve önceki olaylar için milisaniye sürelerini kaydetmeyi içerir. Çok çekici bir çözüm olduğunu söyleyemem ama ...


2
Bu noktaya gelebileceğinden endişelendim.
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); hızlı bir arama olsun ya da olmasın, bu yüzden unicode_mapping nesnesine sahibim. Bu, ultra hızlıysa, bu kodu biraz azaltmak için çıkarılacak bir şey olabilir. Bu, tuş çıkışları için tekrar tekrar çağrılacağından, hız önemlidir, bu nedenle haritayı karamsar bir şekilde ekledim.
RobKohr

1

Aşağıdaki kod kullandığım şey:

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

Kullanıcı Alt tuşunu bir süre (yaklaşık 2 saniye) basılı tuttuğunda, bir grup etiket (sınıf = 'gizli anahtar') görünür. Alt tuşu bırakıldığında etiketler kaybolur. jQuery ve Bootstrap her ikisi de kullanılır.


ve Alt aşağıdayken "Tab" tuşuna basılırsa ne olur?
Michael

1

Bunun çok eski bir soru olduğunu biliyorum, ancak DOM API'yi kullanırken klavye olay işleyicilerinin tutarsız ateşlenmesini etkili bir şekilde "yamalayan" çok hafif (~ .5Kb) bir JavaScript kitaplığı var.

Kütüphane Keydrown'dır .

Dinleyiciyi ayarlayacağım anahtarı değiştirerek amacım için iyi sonuç veren işlemsel kod örneği:

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

Yazdığım bir Red Light Green Light oyununda düzgün bir duraklama animasyonu için Keydrown'u istemci tarafı JavaScript'ime dahil ettim. Oyunun tamamını buradan görüntüleyebilirsiniz . (Not: Gelecekte bunu okuyorsanız, oyun tam kodlu ve oynanabilir olmalıdır: -D!)

Umarım bu yardımcı olur.


1

Yukarıdaki cevapları taradım ve önerilen keydown/ keyupyaklaşım yalnızca özel durumlarda işe yarıyor. Kullanıcı alt-sekmeleri uzaklaştırırsa veya yeni bir tarayıcı penceresi veya sekmesi açmak için bir tuş hareketi kullanırsa, o zaman a keydownkaydedilecektir, bu sorun değildir, çünkü bu noktada anahtarın web uygulamasının izlediği bir şey olup olmadığını anlamak imkansızdır. veya standart bir tarayıcı veya işletim sistemi kısayolu. Tarayıcı sayfasına geri döndüğünde, bu arada piyasaya sürülmesine rağmen yine de anahtarın tutulduğunu düşünecektir. Veya kullanıcı fare ile başka bir sekmeye veya uygulamaya geçerken bazı tuşlar tutulur ve ardından sayfamızın dışında bırakılır.

Değiştirici tuşlar ( Shiftvb.), mousemoveGeri sekme sırasında en az bir fare etkileşiminin beklendiği varsayılarak, vb. Aracılığıyla izlenebilir , ki bu genellikle böyle olur.

Diğer tüm tuşlar çoğu için (değiştiricileri dışında Tab, Deletefakat dahil Space, Enter), izleme keypressçoğu uygulama için çalışacak - kilit yangın devam edecektir aşağı düzenledi. Yine de, keypressateşlemenin periyodikliği nedeniyle anahtarı sıfırlamada bir miktar gecikme var . Temel olarak, keypressateş etmeye devam etmezse, anahtarların çoğunu göz ardı etmek mümkündür. Bu, değiştiricilerle birlikte oldukça hava geçirmez, ancak Tabve ile ne yapacağımı keşfetmedim Backspace.

Eminim bu DOM zayıflığı üzerine özetlerin olduğu bir kitaplık vardır ya da belki bazı DOM standart değişiklikleri bunu halletmiştir, çünkü bu oldukça eski bir soru.


tuşa basma artık kullanımdan kaldırılmıştır. Chrome'da hiç çalışmıyor gibi görünüyor.
eadsjr

0

Bak bu cevap ve kullanım onkeyupve onkeydown. İşte bu olaylar hakkında daha spesifik bilgiler.


1
Alıntı yaptığınız bağlantı, otomatik yinelemenin bir sorun olmadığı fare olayları içindir.
Carl Smotricz

key-up ve key-down tekrarlanmaz. tuşa basma gücü.
Claudiu

öyle olsalar bile, TJMonk15'in çözümü gibi bir şey hayal ediyordum, sadece yazmak istemedim
Claudiu

1
Bu iki sorunun üslubu tamamen aynı. Tuhaf tesadüf mü yoksa daha fazlası mı?
Mitch Lindgren

2
@Mitch: vay ... bu oldukça inanılmaz. Birisinin aynı soruyu sormak için neden iki hesap açtığını bilmiyorum. veya daha büyük olasılıkla bu kişi diğer soruyu kopyaladı ve anahtarlar için uyarladı
Claudiu

0

Bu, Firefox ve Chrome'da çalışır.

EnterSadece dosyayı görüntülemek veya özel bir çevrimiçi düzenleyicide düzenlemek için yerel olarak özel bir html dosyasını açmam gerekiyordu ( Windows'ta dosya gezgininde dosya seçildiğinde düğmesine basarak ).

Bu yüzden Ctrl, basarken-tuşunu basılı tutarak bu iki seçeneği birbirinden ayırmak istedim Enter.

Hepinizin buradaki tüm cevaplardan anladığınız gibi, bu pek mümkün görünmüyor, ama işte bu davranışı benim için kabul edilebilir bir şekilde taklit eden bir yol.

Bunun çalışma şekli şu şekildedir:

CtrlDosyayı açarken- tuşunu basılı tutarsanız , javascript kodunda bir keydown olayı asla tetiklenmez. Ancak bir keyup olayı tetiklenir (sonunda- Ctrltuşunu bıraktığınızda ). Kod bunu yakalar.

Kod ayrıca, biri meydana gelir gelmez önemli olayları (hem anahtarlama hem de tuş bırakma) kapatır. Bu nedenle Ctrl, dosya açıldıktan sonra- tuşuna basarsanız hiçbir şey olmaz.

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 tuşuna basarsanız uyarıyı görürsünüz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.