119 votes

Vérifiez si une touche est enfoncée?

Y a-t-il un moyen de détecter si une touche est actuellement enfoncée en JavaScript?

Je connais l'événement "keydown", mais ce n'est pas ce dont j'ai besoin. Quelque temps APRES que la touche a été pressée, je veux être capable de détecter si elle est toujours enfoncée.

P. S. Le plus grand problème semble être qu'après un certain temps, la touche commence à se répéter, déclenchant des événements keydown et keyup comme un fou. Espérons qu'il existe simplement une fonction isKeyDown(touche), sinon ce problème devra être surmonté / contourné.

10 votes

Un problème courant avec les réponses que je vois ici est que si vous maintenez une touche enfoncée, puis changez d'onglets ou de focus, relâchez la touche, puis revenez en arrière, le code pensera que la touche est enfoncée jusqu'à ce que vous la pressiez à nouveau ou passiez la souris sur la page. :-(

0 votes

Est-ce que cela répond à votre question? JavaScript: Vérifiez si le bouton de la souris est enfoncé?

162voto

Devin G Rhode Points 3669

En plus d'utiliser les écouteurs keyup et keydown pour suivre quand une touche est enfoncée et remontée, il y a en fait certaines propriétés qui vous indiquent si certaines touches sont enfoncées.

window.onmousemove = function (e) {
  if (!e) e = window.event;
  if (e.shiftKey) {/*shift est enfoncée*/}
  if (e.altKey) {/*alt est enfoncée*/}
  if (e.ctrlKey) {/*ctrl est enfoncée*/}
  if (e.metaKey) {/*cmd est enfoncée*/}
}

Ces propriétés sont disponibles sur tous les objets d'événements générés par le navigateur, comme ceux de keydown, keyup et keypress, donc vous n'avez pas besoin d'utiliser mousemove.

J'ai essayé de générer mes propres objets d'événements avec document.createEvent('KeyboardEvent') et document.createEvent('KeyboardEvent') et de chercher e.shiftKey et ainsi de suite, mais je n'ai pas eu de chance.

J'utilise Chrome 17 sur Mac

0 votes

Je l'utilise, dans les nouveaux navigateurs et les anciens, même les HTA

1 votes

Y a-t-il un moyen de mettre en œuvre cette réponse lorsque certains nombres sont actuellement en panne ? J'ai essayé avec if (e.keyCode==49) {console.log("1 est en panne");} mais ça ne fonctionne pas :(

0 votes

Hey @RobertoSepúlvedaBravo Robert semble répondre à votre question dans la réponse suivante. ;)

91voto

bobince Points 270740

Existe-t-il un moyen de détecter si une touche est actuellement enfoncée en JavaScript?

Non. La seule possibilité est de surveiller chaque keyup et keydown et de se souvenir.

après un certain laps de temps, la touche commence à se répéter, déclenchant des événements keydown et keyup comme un démon.

Ça ne devrait pas. Vous obtiendrez certainement des répétitions de keypress, et dans de nombreux navigateurs, vous obtiendrez également des répétitions de keydown, mais si keyup se répète, c'est un bug.

Malheureusement, ce n'est pas un bug complètement inconnu: sur Linux, Chromium, et Firefox (lorsqu'il est exécuté sous GTK+, comme c'est le cas dans des distributions populaires telles que Ubuntu) génèrent tous deux des séquences de répétition de keyup-keypress-keydown pour les touches maintenues, qu'il est impossible de distinguer de quelqu'un qui martèle la touche vraiment rapidement.

18 votes

Vous êtes un gentilhomme et un érudit. Chromium et Firefox sur Ubuntu sont mon environnement de développement principal, ce qui explique précisément le problème que j'ai rencontré. Espérons que cela s'améliorera, sinon cette solution de contournement de piratage de la minuterie pourrait être la seule option.

3 votes

Oui, c'est frustrant qu'il n'y ait pas de progrès sur cela. Voir bugs.launchpad.net/ubuntu/+bug/369880. Je suis en train d'écrire un jeu de navigateur et ma solution temporaire est de me concentrer sur les touches de modification (shift, ctrl, etc.) qui ne se répètent pas du tout.

2 votes

Non, il est possible de les distinguer des frappes de touches répétées authentiques par leur absence d'événements keyup correspondants.

12voto

TJMonk15 Points 2684

Je ne crois pas qu'il existe une fonction isKeyDown, mais vous pourriez écrire la vôtre.

Essentiellement, créez un tableau dont la longueur est le nombre de touches que vous voulez surveiller. Ensuite, en utilisant les événements keyUp et keyDown des documents/pages/contrôles, mettez à jour le tableau avec l'état de cette touche.

Ensuite, écrivez une fonction qui vérifie si une certaine touche est enfoncée et renvoie un booléen.

var keyEnum = { W_Key:0, A_Key:1, S_Key:2, D_Key:3 };
var keyArray = new Array(4);

function onKeyDown()
{
    // Détectez quelle touche a été pressée
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = true;
    // Répétez pour chaque touche qui vous intéresse...
}

function onKeyUp()
{
    // Détectez quelle touche a été relâchée
    if( key == 'w' )
        keyArray[keyEnum.W_Key] = false;
    // Répétez pour chaque touche qui vous intéresse...
}

function isKeyDown(key)
{
    return keyArray[key];
}

Cela devrait accomplir ce que vous voulez.

1 votes

C'est bien, et en effet une partie de la solution, mais cela ne résout pas le bogue de répétition de keyup que je rencontre. Voir la réponse de bobince.

7 votes

Cette solution n'est pas idéale car vous seriez amené à écrire de plus en plus de conditions. Une "keyList = {};" étant un objet accepte "keyList[key] = true;" sans avoir besoin d'une énumération ou d'une limite car elle utilise des index/propriétés de type chaîne de caractères et fonctionne pour toutes les clés.

2voto

RobKohr Points 2022
/*
Suites des touches qui sont actuellement enfoncées sur le clavier
*/

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('Ce sont les touches enfoncées :', kb);
}

var keyboard = keyboard_module(testing);

....
//ailleurs dans le code
if(keyboard['K']){/*faire quelque chose de spécial */}

0 votes

Pas sûr si String.fromCharCode(unicode); est une recherche rapide ou non, c'est pourquoi j'ai un objet unicode_mapping. Cela pourrait être quelque chose à extraire pour réduire un peu ce code s'il est ultra-rapide. Comme cela sera appelé de manière répétée pour les appuis sur les touches, la vitesse est importante, c'est pourquoi j'ai ajouté le mapping de manière pessimiste.

1voto

Carl Smotricz Points 36400

D'autres personnes ont posé ce genre de question auparavant (bien que je ne voie aucun doublon évident ici pour le moment).

Je pense que la réponse est que l'événement keydown (et son jumeau keyup) sont toutes les informations que vous obtenez. La répétition est bien intégrée dans le système d'exploitation, et un programme d'application n'a pas beaucoup l'opportunité d'interroger le BIOS pour l'état réel de la touche.

Ce que vous pouvez faire, et peut-être devez faire si vous avez besoin que cela fonctionne, c'est de débouncer de manière programmatique la touche. Essentiellement, vous pouvez évaluer keydown et keyup vous-même mais ignorer un événement keyup s'il se produit trop rapidement après le dernier keydown... ou essentiellement, vous devriez retarder votre réponse au keyup assez longtemps pour être sûr qu'il n'y a pas un autre événement keydown suivant avec quelque chose comme 0.25 secondes du keyup.

Cela impliquerait d'utiliser une activité de minuterie et d'enregistrer les temps en millisecondes des événements précédents. Je ne peux pas dire que ce soit une solution très attrayante, mais...

2 votes

J'étais inquiet que cela puisse en arriver là.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X