Existe-t-il un moyen de détecter si un bouton de la souris est actuellement enfoncé dans JavaScript?
Je connais l'événement «mousedown», mais ce n'est pas ce dont j'ai besoin. Quelque temps après avoir appuyé sur le bouton de la souris, je veux être en mesure de détecter s'il est toujours enfoncé.
Est-ce possible?
En ce qui concerne la solution de Pax: cela ne fonctionne pas si l’utilisateur clique sur plusieurs boutons de manière intentionnelle ou accidentelle. Ne me demandez pas comment je sais :-(.
Le code correct devrait être comme ça:
var mouseDown = 0;
document.body.onmousedown = function() {
++mouseDown;
}
document.body.onmouseup = function() {
--mouseDown;
}
Avec le test comme ça:
if(mouseDown){
// crikey! isn't she a beauty?
}
Si vous voulez savoir quel bouton est enfoncé, préparez-vous à faire de mouseDown un tableau de compteurs et à les compter séparément pour des boutons distincts:
// let's pretend that a mouse doesn't have more than 9 buttons
var mouseDown = [0, 0, 0, 0, 0, 0, 0, 0, 0],
mouseDownCount = 0;
document.body.onmousedown = function(evt) {
++mouseDown[evt.button];
++mouseDownCount;
}
document.body.onmouseup = function(evt) {
--mouseDown[evt.button];
--mouseDownCount;
}
Maintenant, vous pouvez vérifier quels boutons ont été appuyés exactement:
if(mouseDownCount){
// alright, let's lift the little bugger up!
for(var i = 0; i < mouseDown.length; ++i){
if(mouseDown[i]){
// we found it right there!
}
}
}
Sachez maintenant que le code ci-dessus ne fonctionne que pour les navigateurs conformes aux normes qui vous transmettent un numéro de bouton à partir de 0 et plus. IE utilise un masque de bits des boutons actuellement enfoncés:
Alors ajustez votre code en conséquence! Je le laisse comme un exercice.
Et rappelez-vous: IE utilise un objet événement global appelé… "événement".
Incidemment, IE a une fonctionnalité utile dans votre cas: lorsque d'autres navigateurs envoient "button" uniquement pour les événements de bouton de la souris (onclick, onmousedown et onmouseup), IE l'envoie également avec onmousemove. Ainsi, vous pouvez commencer à écouter onmousemove lorsque vous devez connaître l'état du bouton et rechercher evt.button dès que vous l'avez obtenu - vous savez maintenant quels boutons de la souris ont été enfoncés:
// for IE only!
document.body.onmousemove = function(){
if(event.button){
// aha! we caught a feisty little sheila!
}
};
Bien sûr, vous n'obtenez rien si elle joue morte et ne bouge pas.
Liens pertinents:
Update # 1: je ne sais pas pourquoi j'ai transféré le code de type document.body. Il sera préférable d'attacher des gestionnaires d'événements directement au document.
Je pense que la meilleure approche consiste à conserver votre propre enregistrement de l'état du bouton de la souris, comme suit:
var mouseDown = 0;
document.body.onmousedown = function() {
mouseDown = 1;
}
document.body.onmouseup = function() {
mouseDown = 0;
}
et ensuite, plus tard dans votre code:
if (mouseDown == 1) {
// the mouse is down, do what you have to do.
}
C'est une vieille question, et les réponses ici semblent surtout préconiser d'utiliser mousedown
et mouseup
pour savoir si un bouton est enfoncé. Mais comme d’autres l’ont déjà fait remarquer, mouseup
ne sera déclenché que s’il est exécuté dans le navigateur, ce qui peut entraîner une perte de suivi de l’état du bouton.
Cependant, MouseEvent (maintenant) indique les boutons actuellement utilisés:
MouseEvent.buttons
MouseEvent.which
(buttons
sera indéfini pour Safari). Remarque: which
utilise des nombres différents de buttons
pour les clics droit et moyen.Lorsqu'il est enregistré sur document
, mousemove
est immédiatement déclenché dès que le curseur entre à nouveau dans le navigateur. Ainsi, si l'utilisateur relâche l'utilisateur extérieur, l'état sera mis à jour dès qu'il reviendra à la souris.
Une implémentation simple pourrait ressembler à:
var leftMouseButtonOnlyDown = false;
function setLeftButtonState(e) {
leftMouseButtonOnlyDown = e.buttons === undefined
? e.which === 1
: e.buttons === 1;
}
document.body.onmousedown = setLeftButtonState;
document.body.onmousemove = setLeftButtonState;
document.body.onmouseup = setLeftButtonState;
Si des scénarios plus complexes sont nécessaires (différents boutons/plusieurs boutons/touches de contrôle), consultez la documentation MouseEvent. Quand/si Safari élève son jeu, cela devrait devenir plus facile.
la solution n'est pas bonne ... On peut "coller la souris" sur le document, puis "mouseup" en dehors du navigateur, et dans ce cas, le navigateur penserait toujours que la souris est enfoncée.
la seule bonne solution est d'utiliser l'objet IE.event.
Je sais que ceci est un ancien post, mais je pensais que le suivi du bouton de la souris à l'aide de la souris haut/bas était un peu maladroit; j'ai donc trouvé une alternative qui pourrait plaire à certains.
<style>
div.myDiv:active {
cursor: default;
}
</style>
<script>
function handleMove( div ) {
var style = getComputedStyle( div );
if (style.getPropertyValue('cursor') == 'default')
{
// You're down and moving here!
}
}
</script>
<div class='myDiv' onmousemove='handleMove(this);'>Click and drag me!</div>
Le sélecteur: active gère le clic de la souris beaucoup mieux que la souris en haut/en bas, vous avez juste besoin d’un moyen de lire cet état dans l’événement onmousemove. Pour cela, je devais tricher et me basais sur le fait que le curseur par défaut était "auto" et que je le changeais simplement pour "par défaut", qui est ce que l'auto sélectionne par défaut.
Vous pouvez utiliser tout élément de l'objet renvoyé par getComputedStyle que vous pouvez utiliser en tant qu'indicateur sans perturber l'apparence de votre page, par exemple. couleur de la bordure.
J'aurais aimé définir mon propre style défini par l'utilisateur dans la section: active, mais je ne pouvais pas le faire fonctionner. Ce serait mieux si c'est possible.
L'extrait de code suivant tente d'exécuter la fonction "doStuff" 2 secondes après que l'événement mouseDown se soit produit dans document.body. Si l'utilisateur lève le bouton, l'événement mouseUp se produira et annulera l'exécution différée.
Je conseillerais d'utiliser une méthode pour l'attachement d'événements entre navigateurs - le paramétrage explicite des propriétés mousedown et mouseup a été effectué pour simplifier l'exemple.
function doStuff() {
// does something when mouse is down in body for longer than 2 seconds
}
var mousedownTimeout;
document.body.onmousedown = function() {
mousedownTimeout = window.setTimeout(doStuff, 2000);
}
document.body.onmouseup = function() {
window.clearTimeout(mousedownTimeout);
}
Je ne suis pas sûr de savoir pourquoi aucune des réponses précédentes n'a fonctionné pour moi, mais j'ai proposé cette solution lors d'un moment Eureka. Non seulement ça marche, mais c'est aussi le plus élégant:
Ajouter à la balise body:
onmouseup="down=0;" onmousedown="down=1;"
Puis testez et exécutez myfunction()
si down
est égal à 1
:
onmousemove="if (down==1) myfunction();"
Vous pouvez combiner @Pax et mes réponses pour obtenir également la durée pendant laquelle la souris est hors service:
var mousedownTimeout,
mousedown = 0;
document.body.onmousedown = function() {
mousedown = 0;
window.clearInterval(mousedownTimeout);
mousedownTimeout = window.setInterval(function() { mousedown += 200 }, 200);
}
document.body.onmouseup = function() {
mousedown = 0;
window.clearInterval(mousedownTimeout);
}
Puis plus tard:
if (mousedown >= 2000) {
// do something if the mousebutton has been down for at least 2 seconds
}
Vous devez gérer MouseDown et MouseUp et définir un indicateur ou quelque chose pour le suivre "plus tard sur la route" ... :(
Dans l'exemple ci-dessous, lorsque la souris est au-dessus de $ ('. Élément'), la couleur change en fonction du bouton de la souris sur lequel vous appuyez.
var clicableArea = {
init: function () {
var self = this;
('.element').mouseover(function (e) {
self.handlemouseClick(e, $(this));
}).mousedown(function (e) {
self.handlemouseClick(e, $(this));
});
},
handlemouseClick: function (e, element) {
if (e.buttons === 1) {//left button
element.css('background', '#f00');
}
if (e.buttons === 2) { //right buttom
element.css('background', 'none');
}
}
};
$(document).ready(function () {
clicableArea.init();
});
Si vous travaillez dans une page complexe avec des gestionnaires d'événements de souris existants, je vous recommande de gérer l'événement sur capture (au lieu de bulle). Pour ce faire, il suffit de définir le 3ème paramètre de addEventListener
sur true
.
En outre, vous pouvez vérifier la présence de event.which
pour vous assurer de gérer les interactions utilisateur réelles et non les événements de souris, par exemple. elem.dispatchEvent(new Event('mousedown'))
.
var isMouseDown = false;
document.addEventListener('mousedown', function(event) {
if ( event.which ) isMouseDown = true;
}, true);
document.addEventListener('mouseup', function(event) {
if ( event.which ) isMouseDown = false;
}, true);
Ajoutez le gestionnaire au document (ou à la fenêtre) au lieu de document.body est important car il garantit que les événements mouseup hors de la fenêtre sont toujours enregistrés.
En utilisant MouseEvent api, pour vérifier le bouton enfoncé, le cas échéant:
document.addEventListener('mousedown', (e) => console.log(e.buttons))
Retour :
Un nombre représentant un ou plusieurs boutons. Pour plus d'un bouton enfoncé simultanément, les valeurs sont combinées (par exemple, 3 est primaire + secondaire).
0 : No button or un-initialized 1 : Primary button (usually the left button) 2 : Secondary button (usually the right button) 4 : Auxilary button (usually the mouse wheel button or middle button) 8 : 4th button (typically the "Browser Back" button) 16 : 5th button (typically the "Browser Forward" button)
Comme dit @Jack, lorsque mouseup
se produit en dehors de la fenêtre du navigateur, nous n'en sommes pas conscients ...
window.addEventListener('mouseup', mouseUpHandler, false);
window.addEventListener('mousedown', mouseDownHandler, false);
mouseup
dans l'un de ces cas:Avec jQuery, la solution suivante gère même le "glisser de la page puis relâcher la casse".
$(document).mousedown(function(e) {
mouseDown = true;
}).mouseup(function(e) {
mouseDown = false;
}).mouseleave(function(e) {
mouseDown = false;
});
Je ne sais pas comment il gère plusieurs boutons de la souris . S'il y avait un moyen de démarrer le clic en dehors de la fenêtre, puis amener la souris dans la fenêtre, cela ne fonctionnerait probablement pas correctement là-bas non plus.