Czy istnieje sposób na wykrycie, czy przycisk myszy w JavaScript jest obecnie wyłączony?
Wiem o zdarzeniu „mousedown”, ale nie tego potrzebuję. Jakiś czas PO naciśnięciu przycisku myszy chcę móc wykryć, czy nadal jest wciśnięty.
czy to możliwe?
Czy istnieje sposób na wykrycie, czy przycisk myszy w JavaScript jest obecnie wyłączony?
Wiem o zdarzeniu „mousedown”, ale nie tego potrzebuję. Jakiś czas PO naciśnięciu przycisku myszy chcę móc wykryć, czy nadal jest wciśnięty.
czy to możliwe?
Odpowiedzi:
Odnośnie rozwiązania Pax: nie działa, jeśli użytkownik celowo lub przypadkowo kliknie więcej niż jeden przycisk. Nie pytaj mnie, skąd wiem :-(.
Prawidłowy kod powinien wyglądać tak:
var mouseDown = 0;
document.body.onmousedown = function() {
++mouseDown;
}
document.body.onmouseup = function() {
--mouseDown;
}
Z takim testem:
if(mouseDown){
// crikey! isn't she a beauty?
}
Jeśli chcesz wiedzieć, który przycisk jest wciśnięty, przygotuj się na zrobienie mouseDown tablicę liczników i policz je osobno dla oddzielnych przycisków:
// 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;
}
Teraz możesz sprawdzić, jakie dokładnie przyciski zostały wciśnięte:
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!
}
}
}
Teraz ostrzegamy, że powyższy kod będzie działał tylko w przeglądarkach zgodnych ze standardami, które przekazują ci numer przycisku zaczynający się od 0 i wyżej. IE używa maski bitowej aktualnie wciśniętych przycisków:
Więc odpowiednio dostosuj swój kod! Zostawiam to jako ćwiczenie.
I pamiętaj: IE używa globalnego obiektu zdarzenia o nazwie… „zdarzenie”.
Nawiasem mówiąc, IE ma funkcję przydatną w twoim przypadku: kiedy inne przeglądarki wysyłają „przycisk” tylko dla zdarzeń związanych z przyciskiem myszy (onclick, onmousedown i onmouseup), IE wysyła go również z onmousemove. Możesz więc zacząć nasłuchiwać onmousemove, gdy potrzebujesz znać stan przycisku, i sprawdzać, czy występuje evt.button, gdy tylko go otrzymasz - teraz wiesz, jakie przyciski myszy zostały naciśnięte:
// for IE only!
document.body.onmousemove = function(){
if(event.button){
// aha! we caught a feisty little sheila!
}
};
Oczywiście nic nie dostaniesz, jeśli udaje martwą i się nie rusza.
Odpowiednie linki:
Aktualizacja nr 1 : Nie wiem, dlaczego przeniosłem kod w stylu document.body. Lepiej będzie dołączyć programy obsługi zdarzeń bezpośrednio do dokumentu.
event.buttons
dowolny wyzwalacz zdarzenia, którego używasz, bez zewnętrznych zapisanych zmiennych. Zadałem zupełnie nowe pytanie (ponieważ moje zdarzenie mouseup nie zawsze się uruchamia, więc to rozwiązanie nie działa dla mnie) i otrzymałem tę odpowiedź w ciągu może 5 minut.
To jest stare pytanie, a odpowiedzi tutaj wydają się być zwolennikami używania mousedown
i mouseup
śledzenia, czy przycisk jest wciśnięty. Ale jak zauważyli inni,mouseup
będzie uruchamiany tylko wtedy, gdy jest wykonywany w przeglądarce, co może prowadzić do utraty śledzenia stanu przycisku.
Jednak MouseEvent (teraz) wskazuje, które przyciski są aktualnie wciśnięte:
MouseEvent.buttons
MouseEvent.which
( buttons
będzie niezdefiniowane dla Safari) Uwaga: which
używa innych liczb niż buttons
dla kliknięć prawym i środkowym.Gdy zarejestrowana w dniu document
,mousemove
natychmiast zwolnić, gdy tylko kursor ponownie przechodzi przeglądarkę, więc jeśli użytkownik zwalnia poza to państwo będzie aktualizowany jak tylko mysz z powrotem do środka.
Prosta implementacja może wyglądać następująco:
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;
Jeśli wymagane są bardziej skomplikowane scenariusze (różne przyciski / wiele przycisków / klawisze kontrolne), zapoznaj się z dokumentacją MouseEvent. Kiedy / jeśli Safari podniesie swoją grę, powinno to być łatwiejsze.
e.buttons
zostaną zarówno podstawowe, jak i dodatkowe, będzie 1+2=3
, więc e.buttons === 1
będzie fałszywe). Jeśli chcesz sprawdzić, czy podstawowy przycisk jest w dół, ale nie dbają o innych stanów przycisku, to zrobić:(e.buttons & 1) === 1
MouseEvent.buttons
, wydaje się, że 7
oznacza to, że myśli, że przyciski Primary, Secondary i Auxilary są wciśnięte razem. Nie jestem pewien, dlaczego tak się dzieje - czy używasz zaawansowanej myszy? Jeśli tak, to może warto spróbować z podstawowym. Jeśli potrzebujesz tylko uruchomić, możesz użyć bitowego sprawdzenia, aby upewnić się, że lewy przycisk jest naciśnięty i zignorować inne. na przykład. MouseEvent.buttons & 1 === 1
.
Myślę, że najlepszym podejściem jest zachowanie własnego zapisu stanu przycisku myszy w następujący sposób:
var mouseDown = 0;
document.body.onmousedown = function() {
mouseDown = 1;
}
document.body.onmouseup = function() {
mouseDown = 0;
}
a później w kodzie:
if (mouseDown == 1) {
// the mouse is down, do what you have to do.
}
rozwiązanie nie jest dobre. można by przesunąć kursor myszy na dokument, a następnie przesunąć mysz poza przeglądarkę, aw tym przypadku przeglądarka nadal myślałaby, że mysz nie działa.
jedynym dobrym rozwiązaniem jest użycie obiektu IE.event.
Wiem, że to stary post, ale pomyślałem, że śledzenie przycisku myszy za pomocą myszy w górę / w dół wydawało się nieco niezgrabne, więc znalazłem alternatywę, która może spodobać się niektórym.
<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>
Selektor: active radzi sobie z kliknięciem myszy znacznie lepiej niż myszką w górę / w dół, potrzebujesz tylko sposobu na odczytanie tego stanu w zdarzeniu onmousemove. W tym celu musiałem oszukiwać i polegać na fakcie, że domyślny kursor to „auto” i po prostu zmieniam go na „domyślny”, czyli to, co domyślnie wybiera automatycznie.
Możesz użyć w obiekcie wszystkiego, co jest zwracane przez getComputedStyle, czego możesz użyć jako flagi bez zmiany wyglądu strony, np. Border-color.
Chciałbym ustawić własny styl zdefiniowany przez użytkownika w sekcji: active, ale nie mogłem tego zmusić. Byłoby lepiej, gdyby to było możliwe.
Poniższy fragment kodu spróbuje wykonać funkcję „doStuff” 2 sekundy po wystąpieniu zdarzenia mouseDown w pliku document.body. Jeśli użytkownik podniesie przycisk, nastąpi zdarzenie mouseUp i anuluje opóźnione wykonanie.
Radziłbym użyć jakiejś metody dołączania zdarzeń w różnych przeglądarkach - jawne ustawienie właściwości myszy i myszy zostało zrobione w celu uproszczenia przykładu.
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);
}
Nie jestem pewien, dlaczego żadna z poprzednich odpowiedzi nie zadziałała, ale wpadłem na to rozwiązanie w chwili eureki. Nie tylko działa, ale jest też najbardziej elegancki:
Dodaj do tagu ciała:
onmouseup="down=0;" onmousedown="down=1;"
Następnie przetestuj i wykonaj, myfunction()
jeśli down
równa się 1
:
onmousemove="if (down==1) myfunction();"
Możesz połączyć @Pax i moje odpowiedzi, aby uzyskać również czas, przez jaki mysz była wyłączona:
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);
}
Później:
if (mousedown >= 2000) {
// do something if the mousebutton has been down for at least 2 seconds
}
Musisz obsłużyć MouseDown i MouseUp i ustawić jakąś flagę lub coś, aby śledzić to "później w drodze" ... :(
Jeśli pracujesz na złożonej stronie z istniejącymi programami obsługi zdarzeń myszy, polecam obsługę zdarzenia podczas przechwytywania (zamiast bąbelków). Aby to zrobić, wystarczy ustawić trzeci parametr addEventListener
na true
.
Ponadto możesz chcieć sprawdzić, event.which
czy obsługujesz rzeczywistą interakcję użytkownika, a nie zdarzenia myszy, np 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);
Dodaj moduł obsługi do dokumentu (lub okna) zamiast do document. Body jest ważne b / c zapewnia, że zdarzenia myszy poza oknem są nadal rejestrowane.
Używając interfejsu API MouseEvent , aby sprawdzić wciśnięty przycisk, jeśli jest dostępny:
document.addEventListener('mousedown', (e) => console.log(e.buttons))
Zwrot :
Liczba reprezentująca jeden lub więcej przycisków. W przypadku jednoczesnego naciśnięcia więcej niż jednego przycisku wartości są łączone (np. 3 oznacza główny + dodatkowy).
0 : No button or un-initialized 1 : Primary button (usually the left button) 2 : Secondary button (usually the right button) 4 : Auxilary button (usually the mouse wheel button or middle button) 8 : 4th button (typically the "Browser Back" button) 16 : 5th button (typically the "Browser Forward" button)
Korzystając z jQuery, poniższe rozwiązanie obsługuje nawet „przeciągnij stronę, a następnie zwolnij”.
$(document).mousedown(function(e) {
mouseDown = true;
}).mouseup(function(e) {
mouseDown = false;
}).mouseleave(function(e) {
mouseDown = false;
});
Nie wiem, jak obsługuje wiele przycisków myszy. Gdyby istniał sposób na rozpoczęcie klikania poza oknem, a następnie przeniesienie myszy do okna, prawdopodobnie również tam nie działałoby to poprawnie.
Poniżej przykładu jQuery, kiedy mysz znajduje się nad $ ('. Element'), kolor zmienia się w zależności od tego, który przycisk myszy jest wciśnięty.
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();
});
Jak powiedział @Jack, kiedy mouseup
dzieje się poza oknem przeglądarki, nie jesteśmy tego świadomi ...
window.addEventListener('mouseup', mouseUpHandler, false);
window.addEventListener('mousedown', mouseDownHandler, false);
mouseup
zdarzenia w jednym z tych przypadków:Cóż, nie możesz sprawdzić, czy jest wyłączony po wydarzeniu, ale możesz sprawdzić, czy jest włączony… Jeśli jest włączony… oznacza to, że już nie działa: P lol
Tak więc użytkownik naciska przycisk w dół (zdarzenie onMouseDown) ... a następnie sprawdzasz, czy jest włączony (onMouseUp). Chociaż nie jest to możliwe, możesz zrobić to, czego potrzebujesz.
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;
}
ta wersja dla różnych przeglądarek działa dobrze dla mnie.