JavaScript: проверить, нажата ли кнопка мыши? - PullRequest
120 голосов
/ 27 ноября 2008

Есть ли способ определить, не нажата ли в данный момент кнопка мыши в JavaScript?

Я знаю о событии "mousedown", но это не то, что мне нужно. Через некоторое время после нажатия кнопки мыши я хочу определить, нажата ли она по-прежнему.

Возможно ли это?

Ответы [ 15 ]

131 голосов
/ 27 ноября 2008

Относительно решения Pax: оно не работает, если пользователь нажимает более одной кнопки преднамеренно или случайно. Не спрашивайте меня, откуда я знаю: - (.

Правильный код должен быть таким:

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

С таким тестом:

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

Если вы хотите знать, какая кнопка нажата, будьте готовы сделать mouseDown массивом счетчиков и посчитать их отдельно для отдельных кнопок:

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

Теперь вы можете проверить, какие кнопки были нажаты в точности:

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

Теперь предупреждаем, что приведенный выше код будет работать только для стандартных браузеров, которые передают вам номер кнопки, начиная с 0 и выше. IE использует битовую маску нажатых в данный момент кнопок:

  • 0 для "ничего не нажимается"
  • 1 для левого
  • 2 по праву
  • 4 для среднего
  • и любая комбинация выше, например, 5 для левого + среднего

Так что скорректируйте свой код соответственно! Я оставляю это как упражнение.

И помните: IE использует объект глобального события под названием & hellip; "Событие".

Между прочим, в IE есть функция, полезная в вашем случае: когда другие браузеры отправляют «кнопку» только для событий кнопки мыши (onclick, onmousedown и onmouseup), IE также отправляет ее с onmousemove. Таким образом, вы можете начать прослушивание onmousemove, когда вам нужно узнать состояние кнопки, и проверить evt.button, как только вы его получите & mdash; Теперь вы знаете, какие кнопки мыши были нажаты:

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

Конечно, вы ничего не получите, если она играет мертвой и не двигается.

Соответствующие ссылки:

Обновление # 1 : я не знаю, почему я перенес код в формате document.body. Будет лучше прикрепить обработчики событий непосредственно к документу.

18 голосов
/ 25 февраля 2018

Это старый вопрос, и ответы здесь, по-видимому, в основном требуют использования mousedown и mouseup для отслеживания нажатия кнопки. Но, как отмечали другие, mouseup срабатывает только при выполнении в браузере, что может привести к потере контроля над состоянием кнопки.

Однако MouseEvent (сейчас) указывает, какие кнопки нажимаются в данный момент:

  • Для всех современных браузеров (кроме Safari) используйте MouseEvent.buttons
  • Для Safari используйте MouseEvent.which (buttons будет не определено для Safari) Примечание: which использует разные цифры от buttons для правого и среднего кликов.

При регистрации на document, mousemove будет срабатывать сразу же, как только курсор снова войдет в браузер, поэтому, если пользователь выйдет наружу, состояние будет обновлено, как только они вернутся назад.

Простая реализация может выглядеть так:

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;

Если требуются более сложные сценарии (разные кнопки / несколько кнопок / клавиши управления), ознакомьтесь с документами MouseEvent. Когда / если Safari прекратит игру, это станет проще.

17 голосов
/ 27 ноября 2008

Я думаю, что лучший подход к этому состоит в том, чтобы вести собственную запись состояния кнопки мыши следующим образом:

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

, а затем, позже, в вашем коде:

if (mouseDown == 1) {
    // the mouse is down, do what you have to do.
}
12 голосов
/ 26 декабря 2010

решение не хорошее. можно «навести» на документ, затем «навести курсор мыши» вне браузера, и в этом случае браузер все еще будет думать, что мышь не работает.

единственное хорошее решение - использовать объект IE.event.

6 голосов
/ 05 февраля 2016

Я знаю, что это старый пост, но я подумал, что отслеживание нажатия кнопки мыши с помощью мыши вверх / вниз показалось мне немного неловким, поэтому я нашел альтернативу, которая может понравиться некоторым.

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

Селектор: active обрабатывает щелчок мыши намного лучше, чем мышь вверх / вниз, вам просто нужен способ чтения этого состояния в событии onmousemove. Для этого мне нужно было обмануть и полагаться на то, что курсором по умолчанию является «авто», и я просто изменяю его на «по умолчанию», то есть то, что автоматически выбирает по умолчанию.

Вы можете использовать в объекте все, что возвращается getComputedStyle, что вы можете использовать в качестве флага, не нарушая внешний вид вашей страницы, например границы цвета.

Мне бы хотелось установить свой собственный стиль в разделе: active, но я не смог заставить его работать. Было бы лучше, если это возможно.

4 голосов
/ 27 ноября 2008

Следующий фрагмент попытается выполнить функцию «doStuff» через 2 секунды после того, как событие mouseDown произойдет в document.body. Если пользователь поднимает кнопку, происходит событие mouseUp и отменяется отложенное выполнение.

Я бы посоветовал использовать какой-нибудь метод для кросс-браузерного прикрепления событий - явная установка свойств mousedown и mouseup была сделана для упрощения примера.

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);
}
3 голосов
/ 12 августа 2012

Короткие и сладкие

Я не уверен, почему ни один из предыдущих ответов не работал для меня, но я придумал это решение в момент эврики. Это не только работает, но и наиболее элегантно:

Добавить к тегу тела:

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

Затем протестируйте и выполните myfunction(), если down равно 1:

onmousemove="if (down==1) myfunction();"
2 голосов
/ 30 ноября 2008

Вам нужно обработать MouseDown и MouseUp и установить какой-нибудь флаг или что-то такое, чтобы отслеживать его «позже в будущем» ...: (

2 голосов
/ 27 ноября 2008

Вы можете объединить @Pax и мои ответы, чтобы также получить время, в течение которого мышь не работала:

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

Потом позже:

if (mousedown >= 2000) {
  // do something if the mousebutton has been down for at least 2 seconds
}
0 голосов
/ 21 декабря 2017

Если вы работаете на сложной странице с существующими обработчиками событий мыши, я бы порекомендовал обработать событие на capture (вместо bubble). Для этого просто установите 3-й параметр addEventListener на true.

Кроме того, вы можете проверить наличие event.which, чтобы убедиться, что вы обрабатываете фактическое взаимодействие с пользователем, а не события мыши, например, 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);

Добавьте обработчик в документ (или окно) вместо document.body важно, потому что он / она гарантирует, что события mouseup вне окна все еще записываются.

...