JavaScript: Comprobar si el botón del ratón hacia abajo?


¿Hay alguna forma de detectar si un botón del ratón está actualmente inactivo en JavaScript?

Sé lo del evento "mousedown", pero eso no es lo que necesito. Algún tiempo DESPUÉS de presionar el botón del ratón, quiero ser capaz de detectar si todavía está presionado.

Es esto posible?

Author: TM., 2008-11-27

15 answers

En cuanto a la solución de Pax: no funciona si el usuario hace clic en más de un botón intencionalmente o accidentalmente. No me preguntes cómo lo sé : - (.

El código correcto debe ser así:

var mouseDown = 0;
document.body.onmousedown = function() { 
  ++mouseDown;
}
document.body.onmouseup = function() {
  --mouseDown;
}

Con la prueba como esta:

if(mouseDown){
  // crikey! isn't she a beauty?
}

Si quieres saber qué botón se presiona, prepárate para hacer mouseDown una matriz de contadores y contarlos por separado para botones separados:

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

Ahora puedes comprobar qué botones fueron presionados exactamente:

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!
    }
  }
}

Ahora ser se advirtió que el código anterior solo funcionaría para los navegadores compatibles con el estándar que le pasan un número de botón a partir de 0 y arriba. IE utiliza una máscara de bits de botones presionados actualmente:

  • 0 para "nada se presiona"
  • 1 para izquierda
  • 2 para la derecha
  • 4 para el centro
  • y cualquier combinación de arriba, por ejemplo, 5 para izquierda + centro

Así que ajuste su código en consecuencia! Lo dejo como un ejercicio.

Y recuerda: IE utiliza un evento global objeto llamado event "evento".

Por cierto IE tiene una característica útil en su caso: cuando otros navegadores envían "botón" solo para eventos del botón del ratón (onclick, onmousedown, y onmouseup), IE lo envía con onmousemove también. Por lo tanto, puede comenzar a escuchar onmousemove cuando necesite conocer el estado del botón y verificar evt.botón tan pronto como usted lo consiguió - ahora usted sabe qué botones del ratón fueron presionados:

// for IE only!
document.body.onmousemove = function(){
  if(event.button){
    // aha! we caught a feisty little sheila!
  }
};

Por supuesto, no obtienes nada si ella se hace la muerta y no movimiento.

Enlaces relevantes:

Actualización # 1: No se por qué llevé el documento.cuerpo-estilo de código. Será mejor adjuntar controladores de eventos directamente al documento.

 131
Author: Eugene Lazutkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-08 11:28:15

Creo que el mejor enfoque para esto es mantener su propio registro del estado del botón del ratón, de la siguiente manera:

var mouseDown = 0;
document.body.onmousedown = function() { 
    mouseDown = 1;
}
document.body.onmouseup = function() {
    mouseDown = 0;
}

Y luego, más adelante en su código:

if (mouseDown == 1) {
    // the mouse is down, do what you have to do.
}
 15
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-27 00:48:03

La solución no es buena. uno podría " mousedown "en el documento, luego" mouseup " fuera del navegador, y en este caso el navegador todavía estaría pensando que el ratón está abajo.

La única buena solución es usar IE.objeto evento.

 12
Author: alfred,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-26 08:14:39

Esta es una pregunta antigua, y las respuestas aquí parecen abogar principalmente por usar mousedown y mouseup para realizar un seguimiento de si se presiona un botón. Pero como otros han señalado, mouseup solo se disparará cuando se realice dentro del navegador, lo que puede llevar a perder la pista del estado del botón.

Sin embargo, MouseEvent (ahora) indica qué botones se presionan actualmente:

  • Para todos los navegadores modernos (excepto Safari) use MouseEvent.buttons
  • Para Safari, use MouseEvent.which (buttons nota: which utiliza números diferentes de buttons para los clics Derecho y Medio.

Cuando se registra el document, mousemove se disparará inmediatamente tan pronto como el cursor vuelva a entrar en el navegador, por lo que si el usuario libera fuera, el estado se actualizará tan pronto como vuelva al interior del ratón.

Una implementación simple podría parecerse a:

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 se requieren escenarios más complicados (botones diferentes / múltiples botones / teclas de control), echa un vistazo a los documentos de MouseEvent. Cuando / si Safari levanta su juego, esto debería ser más fácil.

 11
Author: Jono Job,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-25 05:58:54

El siguiente fragmento intentará ejecutar la función "doStuff" 2 segundos después de que ocurra el evento mouseDown en el documento.cuerpo. Si el usuario levanta el botón, se producirá el evento mouseUp y cancelará la ejecución retrasada.

Aconsejaría usar algún método para el archivo adjunto de eventos entre navegadores: establecer las propiedades mousedown y mouseup explícitamente se hizo para simplificar el ejemplo.

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);
}
 4
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-27 00:34:42

Sé que este es un post antiguo, pero pensé que el seguimiento del botón del ratón usando el ratón arriba/abajo se sentía un poco torpe, así que encontré una alternativa que puede atraer a algunos.

<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>

El selector :active maneja el clic del ratón mucho mejor que el ratón arriba/abajo, solo necesita una forma de leer ese estado en el evento onmousemove. Para eso necesitaba hacer trampa y confiaba en el hecho de que el cursor predeterminado es "auto" y solo lo cambio a "default", que es lo que auto selecciona por predeterminado.

Puede usar cualquier cosa en el objeto devuelto por getComputedStyle que pueda usar como bandera sin alterar el aspecto de su página, por ejemplo, border-color.

Me hubiera gustado establecer mi propio estilo definido por el usuario en la sección :active, pero no pude hacerlo funcionar. Sería mejor si fuera posible.

 4
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-27 17:34:36

Corto y dulce

No estoy seguro de por qué ninguna de las respuestas anteriores funcionó para mí, pero se me ocurrió esta solución durante un momento eureka. No solo funciona, sino que también es más elegante:

Añadir a la etiqueta del cuerpo:

onmouseup="down=0;" onmousedown="down=1;"

Entonces prueba y ejecuta myfunction() si down es igual a 1:

onmousemove="if (down==1) myfunction();"
 3
Author: Stanley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-02 18:18:29

Puedes combinar @Pax y mis respuestas para obtener también la duración durante la que el ratón ha estado inactivo:

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

Luego más tarde:

if (mousedown >= 2000) {
  // do something if the mousebutton has been down for at least 2 seconds
}
 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-27 00:54:48

Necesita manejar el MouseDown y MouseUp y establecer alguna bandera o algo para rastrearlo "más tarde en el camino"... :(

 2
Author: Thomas Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-29 22:29:21

Por debajo de jQuery ejemplo, cuando el ratón está sobre $('.elemento'), el color está cambiando dependiendo de qué botón del ratón se presiona.

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();
});
 0
Author: Marcin Żurek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-25 05:05:13

Como se dijo @Jack, cuando mouseup sucede fuera de la ventana del navegador, no somos conscientes de ello...

Este código (casi) funcionó para mí:

window.addEventListener('mouseup', mouseUpHandler, false);
window.addEventListener('mousedown', mouseDownHandler, false);

Desafortunadamente, no obtendré el evento mouseup en uno de esos casos:

  • el usuario presiona simultáneamente una tecla del teclado y un botón del ratón, suelta el botón del ratón fuera de la ventana del navegador y luego suelta la tecla.
  • el usuario presiona dos botones del ratón simultáneamente, suelta un botón del ratón y luego el otro, ambos fuera de la ventana del navegador.
 0
Author: dreadcast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-20 08:14:51

Si está trabajando dentro de una página compleja con controladores de eventos del ratón existentes, le recomendaría manejar el evento en capture (en lugar de bubble). Para hacer esto, simplemente establezca el 3er parámetro de addEventListener en true.

Además, es posible que desee verificar event.which para asegurarse de que está manejando la interacción del usuario real y no los eventos del mouse, por ejemplo, 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);

Agregue el controlador a document (o window) en lugar de document.el cuerpo es importante b / c se asegura de que los eventos mouseup fuera de la ventana todavía se registran.

 0
Author: Micah Miller-Eshleman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 19:09:21

Bueno, no se puede comprobar si está abajo después del evento, pero se puede comprobar si está arriba... Si está arriba.. esto significa que ya no está abajo: P lol

Entonces el usuario presiona el botón hacia abajo (evento onMouseDown) ... y después de eso, comprueba si está arriba (onMouseUp). Mientras no esté, puedes hacer lo que necesites.

 -1
Author: rogeriopvl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-26 22:37:31
        var mousedown = 0;
        $(function(){
            document.onmousedown = function(e){
                mousedown = mousedown | getWindowStyleButton(e);
                e = e || window.event;
                console.log("Button: " + e.button + " Which: " + e.which + " MouseDown: " + mousedown);
            }

            document.onmouseup = function(e){
                mousedown = mousedown ^ getWindowStyleButton(e);
                e = e || window.event;
                console.log("Button: " + e.button + " Which: " + e.which + " MouseDown: " + mousedown);
            }

            document.oncontextmenu = function(e){
                // to suppress oncontextmenu because it blocks
                // a mouseup when two buttons are pressed and 
                // the right-mouse button is released before
                // the other button.
                return false;
            }
        });

        function getWindowStyleButton(e){
            var button = 0;
                if (e) {
                    if (e.button === 0) button = 1;
                    else if (e.button === 1) button = 4;
                    else if (e.button === 2) button = 2;  
                }else if (window.event){
                    button = window.event.button;
                }
            return button;
        }

Esta versión cross-browser funciona bien para mí.

 -1
Author: user2550945,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-04 14:49:49

Usando jQuery, la siguiente solución maneja incluso el "arrastre fuera de la página y luego suelte el caso".

$(document).mousedown(function(e) {
    mouseDown = true;
}).mouseup(function(e) {
    mouseDown = false;
}).mouseleave(function(e) {
    mouseDown = false;
});

No se como maneja múltiples botones del mouse. Si hubiera una manera de iniciar el clic fuera de la ventana, a continuación, llevar el ratón a la ventana, entonces esto probablemente no funcionaría correctamente allí tampoco.

 -1
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-04 20:12:41