JavaScript: Fare düğmesinin basılı olup olmadığını kontrol ettiniz mi?


136

Şu anda JavaScript'te bir fare düğmesinin basılı olup olmadığını tespit etmenin bir yolu var mı?

"Fareli" olayı biliyorum, ama ihtiyacım olan şey bu değil. Fare düğmesine basıldıktan SONRA, hala basılı olup olmadığını tespit edebilmek istiyorum.

Mümkün mü?


14
Sorunuzu cevaplamayan bir Yanıtı neden kabul ediyorsunuz? Fareyle üzerine gelme ve fareyle kaydetme yanlıştır (tarayıcının dışında fareyle açabileceğiniz ve hala sürüklediğinizi düşünebildiğiniz için). Sorununuzdan sonra gelip bu sayfaya ulaşmak tamamen işe yaramaz
Jack

@Jack sorumu cevaplıyor. Lütfen sorumu ve cevabı okuyunuz. Görünüşe göre 100'den fazla kişi bunun iyi bir cevap olduğunu kabul ediyor.
TM.

4
evet .. ama ben, alfred, ve diğer 8 size mouseup ve fareyi izlemenin doğru yol olmadığını söylüyor. Doğru cevap, seçtiğiniz işleyicideki olay nesnesinin analizini veya olay güdümlü bir kontrol yerine zaman odaklı kontrole ihtiyacınız varsa fare ile ilgili tüm olayların (enter / exit gibi) analizini içermelidir.
Jack

Bu soru soruldu ve 7+ yıl önce cevaplandı. Yeni yanıtlar olduğunda bildirim almıyorum (ancak yorumlar için yapıyorum). Daha iyi bir cevap yazın ve topluluk en üste vuracaktır :) Çok fazla bilgi eski ve değişiyor.
TM.

2
@TM. Necro için özür dilerim, ama ... Hayır, bu bilgi asla zirveye ulaşmayacak. Bir selfanswer olmayan, bir kez kabul edildiğinde, sonsuza kadar zirveye yapışır. Ayrıca, "ah pek çok kişi buna oy verdi" cevabının iyi olduğu anlamına gelmez; sadece birçok insanın gördüğü, iyi göründüğünü ve üst oyu aldığını, çünkü onlar için çalışıyor gibi göründüğü anlamına gelir.
Monica'nın Davası

Yanıtlar:


147

Pax'ın çözümü ile ilgili olarak: kullanıcı bilerek veya yanlışlıkla birden fazla düğmeyi tıklarsa çalışmaz. Bana nasıl bildiğimi sorma :-(.

Doğru kod şöyle olmalıdır:

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

Bu testle:

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

Hangi düğmeye basıldığını bilmek istiyorsanız, mouseDown'ı bir dizi sayaç yapmaya hazırlayın ve ayrı düğmeler için ayrı ayrı sayın:

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

Şimdi hangi düğmelere tam olarak basıldığını kontrol edebilirsiniz:

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

Şimdi yukarıdaki kodun yalnızca 0 ve daha yukarıdan itibaren bir düğme numarası ileten standart uyumlu tarayıcılarda çalışacağı konusunda uyarınız. IE, şu anda basılan düğmelerin bit maskesini kullanır:

  • "Hiçbir şeye basılmaz" için 0
  • 1 sol için
  • 2 sağ için
  • Orta için 4
  • ve yukarıdaki herhangi bir kombinasyon, örneğin sol + orta için 5

Kodunuzu buna göre ayarlayın! Bir egzersiz olarak bırakıyorum.

Unutmayın: IE,… "event" adlı genel bir olay nesnesi kullanır.

Bu arada IE sizin durumunuzda kullanışlı bir özelliğe sahiptir: diğer tarayıcılar sadece fare düğmesi olayları (onclick, onmousedown ve onmouseup) için "düğme" gönderdiğinde, IE de onmousemove ile gönderir. Böylece düğme durumunu bilmeniz gerektiğinde çok fazla dinlemeye başlayabilir ve en kısa sürede evt düğmesini kontrol edebilirsiniz - şimdi hangi fare düğmelerine basıldığını biliyorsunuz:

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

Elbette eğer ölü oynar ve hareket etmezse hiçbir şey elde edemezsiniz.

İlgili bağlantılar:

Güncelleme # 1 : Belgeyi neden taşıdığımı bilmiyorum. Gövde tarzı kod. Olay işleyicilerini doğrudan belgeye eklemek daha iyi olacaktır.


1
Testten sonra, evt.düğmesinin aslında IE7 ...
TM

5
Bunun Chrome'da çalışmadığını düşünüyorum, çünkü orijinal fareyle bir kaydırma çubuğunda gerçekleştiğinde Chrome fare olayları oluşturmaz. Bir örnek , gelen bu Chrome / Chromium sorunu . Eğer birinin kullandığı bir kaydırma çubuğu varsa, sol fare düğmeniz sonsuza kadar kapalı olacaktır! (Chrome'da)
KajMagnus

1
Çözümünüzü seviyorum, ama fare farklı bir uygulamadan geliyorsa ms kelimesini ve bazı metni sürükleyerek söyleyin. Farenin kapalı olduğunu nasıl tespit edeceksiniz?
Shadrack B.Orina

6
İkinci örnekte fareyle ayrılmış dizi eltlerini neden artırdığınızı anlamıyorum. Neden her bir düğme için bir bool yerine her bir düğme için bir sayaç?
amwinter

2
Bu gerçekten popüler bir soru (ve cevap). Bunun henüz ortaya çıkmadığına şaşırdım, ancak fare verilerini depolamanıza gerek yok. Sadece takabilirsiniz event.buttonsharici kaydedilmiş değişkenler olmadan, kullandığınız ne olursa olsun olay tetikleyici içine. Yepyeni bir soru sordum (çünkü fare olayım her zaman tetiklenmiyor, bu yüzden bu çözüm benim için çalışmıyor) ve bu cevabı belki 5 dakika içinde aldım.
RoboticRenaissance

32

Bu eski bir soru ve buradaki cevaplar çoğunlukla bir düğmeye basıp basılmadığını takip etmek mousedownve kullanmak için savunuyor gibi görünüyor mouseup. Ancak diğerlerinin de belirttiği gibi mouseup, yalnızca tarayıcı içinde gerçekleştirildiğinde ateşlenir, bu da düğme durumunun izini kaybetmesine neden olabilir.

Ancak, MouseEvent (şimdi) şu anda hangi düğmelere basıldığını gösterir:

  • Tüm modern tarayıcılar için (Safari hariç) MouseEvent.buttons
  • Safari için kullanın MouseEvent.which( Safari buttonsiçin tanımsız olacaktır) Not: Sağ ve Orta tıklamalar için whichfarklı sayılar kullanır buttons.

Kayıt işlemi yapıldığında document, mousemoveimleç tarayıcıyı yeniden girer girmez hemen tetiklenir, bu nedenle kullanıcı dışarıda bırakılırsa, tekrar fareye girer girmez durum güncellenir.

Basit bir uygulama şöyle görünebilir:

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;

Daha karmaşık senaryolar gerekiyorsa (farklı düğmeler / çoklu düğmeler / kontrol tuşları), MouseEvent belgelerine bakın. Safari oyununu ne zaman kaldırırsa / kaldırırsa, bu daha kolay olmalıdır.


6
Bu kod SADECE birincil düğmeye basıldığını kontrol eder ve diğer tüm düğmelere basılmasını gerektirir. (hem primer hem sekonder basılırsa, örneğin e.buttonsolacak 1+2=3, bu yüzden e.buttons === 1yanlış olacaktır). Birincil düğmenin basılı olup olmadığını kontrol etmek istiyorsanız, ancak diğer düğme durumlarını umursamıyorsanız, bunu yapın:(e.buttons & 1) === 1
AJ Richardson

Bir mousemove sırasında düğmeleri kodu '1' olması gerekir beklediğim bir durum var ama '7' üretir, - tüm çalışma Chrome üzerinde. Birinin bir fikri var mı?
Vasily Hall

@VasilyHall için MDN docs baktığımızda MouseEvent.buttons, gibi görünüyor 7o Birincil, İkincil ve Yardımcı düğmeleri tüm varlık birlikte preslenmiş olduğunu düşündüğü anlamına gelir. Neden böyle olacağından emin değilim - gelişmiş bir fare mi kullanıyorsunuz? Eğer öyleyse, belki de temel biriyle denemeye değer. Sadece devam ettirmeniz gerekiyorsa, sol düğmeye basıldığından emin olmak ve diğerlerini yoksaymak için bitsel bir kontrol kullanabilirsiniz . Örneğin. MouseEvent.buttons & 1 === 1.
Jono Job

Teşekkür ederim, JavaScript'imi özel bir tarayıcıda kullanıyordum: Adobe Illustrator uygulaması içindeki gömülü Chrome (ium?) . Bunun uygulamamda nasıl tutarlı olduğunu görünce, etkileşimimi kolaylaştırmak için 1 veya 7 için bir kontrol yapıyorum. Logitech M570 (veya her ne olursa olsun) trackball faresini kullanmamıza rağmen, 1'i normal tarayıcıya, ancak Illustrator'ın içindeki 7'ye doğru olarak kaydeder.
Vasily Salonu

16

Bunun için en iyi yaklaşımın fare düğmesi durumuyla ilgili kendi kayıtlarınızı aşağıdaki gibi tutmak olduğunu düşünüyorum:

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

ve daha sonra kodunuzda:

if (mouseDown == 1) {
    // the mouse is down, do what you have to do.
}

+1 ve teşekkürler. Buna başvurmam gerekebileceğini düşündüm, ama sadece durumu doğrudan kontrol etmenizi sağlayan bir özellik olduğunu umuyordum.
TM.

12
Bir boole kullanmamanın bir nedeni var mı?
moala

1
@moala Bence Int daha az yazarak ve sonuçta biraz daha iyi bir performans gibi görünüyor: jsperf.com/bool-vs-int
Johnathan Elmore

12

çözüm iyi değil. biri belgenin üzerinde "fareyle durdurulabilir", ardından tarayıcının dışında "fare ile tıklanabilir" ve bu durumda tarayıcı farenin kapalı olduğunu düşünürdü.

tek iyi çözüm IE.event nesnesini kullanmaktır.


11
Nereden geldiğini görüyorum, ancak sadece IE için çalışan bir çözüme sahip olmak da iyi bir çözüm değil.
TM.

@alfred Bazı durumlarda farenin pencereden dışarı çıkıp çıkmadığını bilmek yardımcı olabilir. (Event.target.nodeName.toLowerCase === 'html') ise = 0 aşağı;
BF

6

Bu eski bir yazı olduğunu biliyorum, ama fare yukarı / aşağı kullanarak fare düğmesinin izlenmesi biraz tıknaz hissettim, bu yüzden bazılarına hitap edebilecek bir alternatif buldum.

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

: Aktif seçici fare tıklamasını farenin yukarı / aşağı yönünden çok daha iyi işler, sadece bu durumu çok büyük olayda okuma yoluna ihtiyacınız vardır. Bunun için hile yapmak ve varsayılan imlecin "otomatik" olduğu gerçeğine güvenmek zorunda kaldım ve sadece varsayılan olarak seçtiği "varsayılan" olarak değiştirdim.

GetComputedStyle tarafından döndürülen nesnede, sayfanızın görünümünü, örneğin kenarlık rengini bozmadan bayrak olarak kullanabileceğiniz herhangi bir şey kullanabilirsiniz.

Aktif bölümünde kendi kullanıcı tanımlı stilim ayarlamak isterdim, ama işe yaramadı. Mümkünse daha iyi olurdu.


Bunu paylaştığın için teşekkürler. Bu fikri sürükle ve bırak stil mantığı için kullanıyordum, ancak IE'de bir sorunla karşı karşıya kaldım ve ek mantık eklemek
Eyüp Yusein

4

Aşağıdaki snippet, document.body dosyasında mouseDown olayının gerçekleşmesinden 2 saniye sonra "doStuff" işlevini yürütmeye çalışır. Kullanıcı düğmeyi kaldırırsa, mouseUp olayı gerçekleşir ve gecikmeli yürütmeyi iptal eder.

Çapraz tarayıcı olay eki için bazı yöntem kullanmanızı öneririm - mousedown ve mouseup özelliklerini açıkça ayarlamak örneği basitleştirmek için yapıldı.

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

Teşekkürler, ancak bu aradığım davranış değil (her ne kadar sorumun bunu yapmaya çalıştığımın bu olduğunu gösterdiğini görebiliyorum).
TM.

3

Kısa ve güzel

Önceki cevapların hiçbirinin benim için neden işe yaramadığından emin değilim, ama bu çözümü bir eureka anı sırasında buldum. Sadece işe yaramaz, aynı zamanda en zarif olanıdır:

Gövde etiketine ekle:

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

Ardından aşağıdakilere eşit myfunction()olup olmadığını test edin ve çalıştırın :down1

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

4
sen yenisin, bu yüzden sana biraz yardım edeceğim, burada. Öncelikle, yazılarınızdaki dilbilgisine dikkat edin - Muhtemelen onu düzelttiğinizden daha fazla zaman harcadım. İkincisi, çözümünüz yukarıda listelenen diğerlerinin sadece başka bir versiyonudur - yeni bir şey değildir. Üçüncüsü, çözümünüzde Thomas Hansen'ın önerdiği "bayrakları kullanma" adı verilen bir teknik kullanılmaktadır. Diğer çözümlerin sizin için neden işe yaramadığına dair bir açıklama yapmadan, dilbilginizi kontrol etmeye ve eski yayınlara gönderim yaparken çözümleri tekrarlamamaya dikkat edin.
Zachary Kniebel

5
Ancak, geçerli olduğu ve SO için yeni olduğunuz için
çözümünüzü oyladım

2

@Pax ve yanıtlarımı birleştirerek farenin kapalı olduğu süreyi de alabilirsiniz:

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

Daha sonra:

if (mousedown >= 2000) {
  // do something if the mousebutton has been down for at least 2 seconds
}

Bu kötü bir fikir değil Jake. Fareyle üzerine gelme süresi 0 olarak ayarlanmadan önce onmouseup () içindekiInInvalval () öğesini temizlemeniz mi gerekiyor? Zamanlayıcı işlevinin 0'a ayarlanması ve zamanlayıcıyı durdurması, zaman aşımının 200'de kalması arasında ateşleme konusunda ihtiyatlıyım? Benzer şekilde onmousedown'da.
paxdiablo

ClearIntervals'ın sırası, geçerli yürütme iş parçacığı (zamanlayıcılar dahil) herhangi bir olay tetiklenmeden önce tamamlanacağı için bir fark yaratmayacaktır.
Nathaniel Reinhart

2

MouseDown ve MouseUp'ı kullanmanız ve "daha sonra yolda" izlemek için bir bayrak veya başka bir şey ayarlamanız gerekir ... :(


2

Mevcut fare olay işleyicileriyle karmaşık bir sayfada çalışıyorsanız, etkinliği yakalamada (kabarcık yerine) ele almanızı öneririm . Bunu yapmak için, sadece 3. parametreyi ayarlamak addEventListeneriçin true.

Ayrıca, event.whichfare olaylarını değil, gerçek kullanıcı etkileşimini kullandığınızdan emin olmak isteyebilirsiniz 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);

İşleyiciyi belge yerine belgeye (veya pencereye) ekleyin. Gövde önemlidir b / c pencerenin dışındaki fare olaylarının hala kaydedilmesini sağlar.


1

MouseEvent API'sini kullanarak , varsa basılan düğmeyi kontrol edin:

document.addEventListener('mousedown', (e) => console.log(e.buttons))

Dönüş :

Bir veya daha fazla düğmeyi temsil eden sayı. Aynı anda birden fazla düğmeye basıldığında, değerler birleştirilir (örneğin, 3 birincil + ikincil).

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)

0

JQuery kullanarak, aşağıdaki çözüm "sayfayı sürükleyip ardından büyük / küçük harf kullanımını" halleder.

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

Birden fazla fare düğmesini nasıl işlediğini bilmiyorum. Tıklamayı pencerenin dışında başlatmanın bir yolu olsaydı, fareyi pencereye getirin, bu muhtemelen orada da düzgün çalışmazdı.


0

JQuery örneğinin altında, fare $ ('. Öğesi') üzerindeyken, hangi fare düğmesine basıldığına bağlı olarak renk değişiyor.

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

0

Dediği gibi @ Jack, ne zaman mouseup tarayıcı penceresinin dışında , bunun farkında değiliz ...

Bu kod (neredeyse) benim için çalıştı:

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

Ne yazık ki, mouseupbu durumlardan birinde olayı almayacağım :

  • kullanıcı aynı anda bir klavye tuşuna ve bir fare düğmesine basar, tarayıcı penceresinin dışındaki fare düğmesini serbest bırakır ve ardından tuşu serbest bırakır.
  • kullanıcı aynı anda iki fare düğmesine basar , her ikisi de tarayıcı penceresinin dışında bir fare düğmesini ve diğerini serbest bırakır.

-1

Peki, olaydan sonra aşağı olup olmadığını kontrol edemezsiniz, ancak Yukarı olup olmadığını kontrol edebilirsiniz.

Böylece kullanıcı düğmeye basar (onMouseDown olayı) ... ve bundan sonra, yukarı (onMouseUp) olup olmadığını kontrol edersiniz. Her şey yolunda olmasa da, ihtiyacınız olanı yapabilirsiniz.


2
OnMouseUp da bir etkinlik değil mi? Mouseup üzerindeki "mülkü" nasıl kontrol edeceksiniz? Ya da kimin malı?
Rohit

@Rohit: özelliği kontrol etmiyorsunuz, olayın gerçekleştiğini belirten bir bayrak yönetiyorsunuz ... Fare düğmesi yukarı veya aşağı.
PhiLho

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

bu çapraz tarayıcı sürümü benim için iyi çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.