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


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

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

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

15 108

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 и выше. Т. е. использует немного маски в настоящее время нажатой кнопки:

  • 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. Для этого мне нужно было обмануть и полагаться на то, что курсор по умолчанию является "auto" , и я просто меняю его на" default", что и выбирает auto по умолчанию.

вы можете использовать что-либо в объекте, возвращаемом 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;
});

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