JavaScript: Verifique se o botão do mouse para baixo?
-
11-07-2019 - |
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?
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 ??li>
- 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
(vontadebuttons
ser indefinido para o Safari) Nota:which
usa números diferentes debuttons
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.