На JavaScript: проверить, если кнопка мыши?

есть ли способ определить, находится ли кнопка мыши в настоящее время в JavaScript?

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

это возможно?

15 ответов


Что касается решения 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 использует глобальный объект события под названием ... "событие".

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

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

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

полезные ссылки:

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


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

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

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

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


это старый вопрос, и ответы здесь, похоже, в основном выступают за использование 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 поднимает свою игру, это должно стать проще.


следующий фрагмент попытается выполнить функцию "doStuff" через 2 секунды после события mouseDown в документе.тело. Если пользователь поднимет кнопку, произойдет событие 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);
}

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

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

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

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

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


короткий и сладкий

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

добавить в тег body:

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

затем проверить и выполнить myfunction() Если down равна 1:

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

вы можете объединить @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
}

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


ниже примера jQuery, когда мышь находится над $('.элемент'), цвет меняется в зависимости от того, какая кнопка нажата.

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

как сказал @Jack, когда mouseup происходит за пределами окна браузера, мы не знаем об этом...

этот код (почти) работал для меня:

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

к сожалению, я не получу mouseup событие в одном из этих случаев:

  • пользователь одновременно нажимает клавишу клавиатуры и кнопку мыши, отпускает кнопку мыши за пределами окна браузера, а затем отпускает клавишу.
  • пользователь нажимает два кнопки мыши одновременно, релизы одна кнопка мыши, затем другая, как за пределами окна браузера.

если вы работаете на сложной странице с существующими обработчиками событий мыши, я бы рекомендовал обрабатывать событие на захват (вместо пузыря). Для этого просто установите 3-й параметр addEventListener to 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);

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


Ну, вы не можете проверить, если это после события, но вы можете проверить, если это случилось... Если он поднят.. это означает, что больше не вниз: P lol

таким образом, пользователь нажимает кнопку вниз (onmousedown событие) ... и после этого вы проверяете, если вверх (onMouseUp). Пока он не поднят, вы можете делать то, что вам нужно.


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

это кросс-браузерная версия отлично работает для меня.


используя jQuery, следующее решение обрабатывает даже "перетащите страницу, а затем отпустите случай".

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

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