Pergunta

Existe uma maneira de detectar se um botão do mouse é atualmente para baixo em JavaScript?

Eu sei sobre o evento "mousedown", mas isso não é o que eu preciso. Algum tempo após o botão do mouse é pressionado, eu quero ser capaz de detectar se ele ainda está pressionado.

Isso é possível?

Foi útil?

Solução

Em relação solução Pax': ele não funciona se o usuário clica mais de um botão intencionalmente ou acidentalmente. Não me pergunte como eu sei: -. (

O código correto deve ser assim:

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

Com o teste como este:

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

Se você quer saber o que o botão é pressionado, estar preparado para fazer mouseDown um conjunto de contadores e contá-los separadamente para botões 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;
}

Agora você pode verificar quais botões foram pressionados exatamente:

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

Agora, ser avisado de que o código acima iria funcionar apenas para navegadores padrão-compliant que passam-lhe um número botão a partir de 0 e para cima. IE usa uma máscara de bits de botões atualmente pressionados:

  • 0 por "nada é pressionado"
  • 1 para esquerda
  • 2 para a direita
  • 4 para meio
  • e qualquer combinação dos acima, por exemplo, 5 para a esquerda + meio

Assim, ajustar o seu código de acordo! Eu deixá-lo como um exercício.

E lembre-se:. IE usa um objeto de evento global chamado ... "evento"

A propósito IE tem uma característica útil no seu caso: quando outros navegadores enviar "botão" apenas para eventos de botão do mouse (onclick, onmousedown e OnMouseUp), IE envia-lo com onmousemove também. Então você pode começar a ouvir para onmousemove quando você precisa saber o estado do botão, e verificar se há evt.button assim que você conseguiu - agora você sabe o que os botões do mouse foram pressionados:

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

É claro que você não ganha nada se ela desempenha mortos e não em movimento.

Links relevantes:

Atualização nº 1 : Eu não sei por que eu carregava sobre o estilo document.body de código. Será melhor para anexar manipuladores de eventos diretamente para o documento.

Outras dicas

Esta é uma questão de idade, e as respostas aqui parecem defender principalmente para usando mousedown e mouseup para acompanhar se um botão é pressionado. Mas, como outros apontaram, mouseup só será acionado quando realizada dentro do navegador, que pode levar a perder de vista o estado do botão.

No entanto, MouseEvent (agora) indica quais botões são atualmente empurrado:

  • Para todos os navegadores modernos (exceto Safari) use MouseEvent.buttons
  • Para Safari, use MouseEvent.which (vontade buttons ser indefinido para o Safari) Nota: which usa números diferentes de buttons de direito e cliques Média
  • .

Quando registrado em document, mousemove vai disparar imediatamente assim que o cursor entra novamente no navegador, por isso, se os lançamentos de usuários fora, em seguida, o estado será atualizado assim que o mouse de volta para dentro.

Uma implementação simples pode parecer:

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;

Se cenários mais complicados são necessários (botões diferentes / vários botões / teclas de controle), confira os docs MouseEvent. Quando / se Safari levanta seu jogo, este deve ficar mais fácil.

Eu acho que a melhor abordagem para isso é manter o seu próprio recorde do estado botão do mouse, como se segue:

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

e, em seguida, mais tarde no código:

if (mouseDown == 1) {
    // the mouse is down, do what you have to do.
}

a solução não é boa. pode-se "mousedown" sobre o documento, em seguida, "mouseup" fora do navegador, e em Neste caso, o navegador ainda estaria pensando o mouse está para baixo.

a única boa solução é usar IE.event objeto.

Eu sei que este é um post antigo, mas achei que o rastreamento de botão do mouse usando o mouse para cima / baixo sentiu um desajeitado pouco, então eu encontrei uma alternativa que pode apelar para alguns.

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

As alças: seletor de ativos o clique do mouse muito melhor do que o mouse para cima / baixo, você só precisa de uma maneira de ler esse estado em caso onmousemove. Para que eu precisava para enganar e contou com o fato de que o cursor padrão é "auto" e eu simplesmente mudá-lo para "default", que é o auto seleciona por padrão.

Você pode usar qualquer coisa no objeto que é retornado por getComputedStyle que você pode usar como uma bandeira, sem prejudicar o visual da sua página de exemplo border-color.

Eu teria gostado de definir meu próprio utilizador do estilo definido na: seção ativa, mas eu não podia chegar a esse trabalho. Seria melhor se é possível.

O seguinte trecho tentará executar a função "doStuff" 2 segundos após o evento mouseDown ocorre em document.body. Se o usuário levanta-se o botão, o evento mouseUp ocorrerá e cancelar a execução demorada.

Eu aconselho usar algum método para a fixação evento cross-browser - definindo o mousedown e mouseUp propriedades explicitamente foi feito para simplificar o exemplo.

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

Curto e doce

Eu não sei por que nenhuma das respostas anteriores funcionou para mim, mas eu vim com esta solução durante um momento eureka. Ela não só funciona, mas também é mais elegante:

Adicionar a tag body:

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

teste Então e executar myfunction() se down igual 1:

onmousemove="if (down==1) myfunction();"

Você pode combinar @Pax e minhas respostas também obter a duração que o rato tem sido baixo para:

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

Então, mais tarde:

if (mousedown >= 2000) {
  // do something if the mousebutton has been down for at least 2 seconds
}

Você precisa lidar com o MouseDown e MouseUp e definir alguns bandeira ou algo para segui-lo "mais tarde abaixo da estrada" ...: (

Usando jQuery, as seguintes alças solução ainda a "arrastar para fora da página e solte caso".

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

Eu não sei como ele lida com vários botões do mouse. Se houvesse uma maneira de começar o clique fora da janela, em seguida, trazer o mouse para a janela, então isso provavelmente não funcionar corretamente lá.

Abaixo jQuery exemplo, quando o mouse é mais de US $ ( 'elemento'), cor está mudando dependendo de qual botão do mouse é pressionado.

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

Como disse @jack, quando mouseup acontece fora da janela do navegador, não temos conhecimento dele ...

Este código (quase) trabalhou para mim:

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

Infelizmente, não vou conseguir o evento mouseup em um desses casos:

  • usuário pressiona simultaneamente uma tecla do teclado e um botão do mouse, libera o botão do mouse para fora da janela do navegador, em seguida, libera-chave.
  • usuário pressiona dois botões do mouse simultaneamente, libera um botão do mouse então o outro, ambos fora da janela do navegador.

Se você está trabalhando dentro de uma página complexo com manipuladores de eventos rato existentes, eu recomendo manipular o evento em captura (em vez de bolha). Para fazer isso, basta definir o terceiro parâmetro de addEventListener para true.

Além disso, você pode querer verificar para event.which para garantir que você está lidando com interação do usuário real e não eventos de mouse, por exemplo, 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);

Adicione o manipulador de documento (ou janela) em vez de document.body é importante b / c ele garante que os eventos mouseup fora da janela estão ainda gravadas.

Bem, você não pode verificar se é para baixo após o evento, mas você pode verificar se ele está acima ... Se é até .. isso significa que não é mais baixo: P lol

Assim, o usuário pressiona o botão para baixo (onMouseDown evento) ... e depois disso, você verificar se é para cima (onMouseUp). Enquanto não é para cima, você pode fazer o que você precisa.

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

Nesta versão cross-browser funciona bem para mim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top