JavaScript:检查鼠标按钮是否按下?


136

有没有一种方法可以检测JavaScript中的鼠标按钮当前是否处于按下状态?

我知道“ mousedown”事件,但这不是我所需要的。按下鼠标按钮后的一段时间,我希望能够检测它是否仍被按下。

这可能吗?


14
为什么您接受不能回答您问题的答案。注册mousedown和mouseup是错误的(因为您可以在浏览器之外进行mouseup并让它认为您仍在拖动)。追问您的问题并到达此页面完全没有用
杰克

@杰克确实回答了我的问题。请阅读我的问题,然后阅读答案。显然有100多个其他人同意这是一个很好的答案。
TM。

4
是的..但是我,阿尔弗雷德(Alfred)和其他8个人告诉您,跟踪mouseup和mousedown不是正确的方法。正确答案应该包括在您选择的处理程序中分析事件对象,或者如果需要时间驱动检查而不是事件驱动检查,则分析所有与鼠标相关的事件(例如enter / exit)。
杰克

7年前问并回答了这个问题。有新答案时,我不会收到通知(但我会发表评论)。写下一个更好的答案,社区将把它提高到最高:)许多信息变得陈旧,情况发生了变化。
TM。

2
@TM值。抱歉,necro,但是...不,该信息永远不会登顶。一旦被接受,非自我回答将永远停留在最顶端。另外,“哦,有这么多人投票支持这个”并不意味着答案是一个好答案。这只是意味着很多人看到了它,认为它看起来还不错,并投票赞成,因为它似乎对他们有用。
基金莫妮卡的诉讼

Answers:


147

关于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使用一个名为…“ event”的全局事件对象。

顺便说一句,IE具有一种适用于您的情况的功能:当其他浏览器仅针对鼠标事件(onclick,onmousedown和onmouseup)发送“ button”时,IE也会通过onmousemove发送它。因此,当您需要了解按钮状态时就可以开始监听onmousemove,并在获取按钮后立即检查evt.button -现在您知道按下了哪些鼠标按钮:

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

当然,如果她死了而且不动,你什么也得不到。

相关链接:

更新#1:我不知道为什么要保留document.body样式的代码。最好将事件处理程序直接附加到文档。


1
经过测试,看来evt.button实际上在IE7 ...
TM上

5
我认为这在Chrome中不起作用,因为如果原始的mousedown发生在滚动条上,Chrome不会生成mouseup事件。一个例子,来自这个Chrome / Chromium问题。因此,如果有人使用滚动条,则鼠标左键将永远处于按下状态!(在Chrome中)
KajMagnus 2012年

1
我喜欢您的解决方案,但是如果鼠标来自其他应用程序,会说ms word及其拖动一些文本怎么办。您将如何检测到鼠标已按下?
Shadrack B. Orina

6
我不明白为什么您要在第二个示例中增加mousedown数组elts。为什么要为每个按钮设置一个计数器,而不是为每个按钮设置布尔值?
2013年

2
这是一个非常受欢迎的问题(和答案)。令我感到惊讶的是,还没有出现,但是您根本不需要存储鼠标数据。您可以插入event.buttons正在使用的任何事件触发器,而无需外部保存的变量。我问了一个全新的问题(因为我的mouseup事件并不总是触发,因此该解决方案对我而言不起作用),并可能在5分钟内获得答案。
RoboticRenaissance 2015年

32

这是一个古老的问题,这里的答案似乎主要提倡使用mousedownmouseup跟踪按钮是否被按下。但正如其他人指出的那样,mouseup只有在浏览器中执行时才会触发,这可能会导致无法跟踪按钮状态。

但是,MouseEvent(现在)指示当前按下了哪些按钮:

  • 对于所有现代浏览器(Safari除外),请使用 MouseEvent.buttons
  • 对于Safari浏览器,使用MouseEvent.whichbuttons将不确定的Safari浏览器)注:which从使用不同数量buttons的右和中间点击。

当在上注册时documentmousemove一旦光标重新进入浏览器,它将立即触发,因此,如果用户释放到外部,则只要将鼠标移回内部,状态就会更新。

一个简单的实现可能看起来像:

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取消其游戏,这应该会变得更加容易。


6
此代码检查是否仅按下了主按钮,并且要求所有其他按钮都未按下。(例如,如果同时按下了primary和secondary,e.buttons则将为1+2=3,因此e.buttons === 1将为false)。如果要检查主按钮是否按下,但不关心其他按钮状态,请执行以下操作:(e.buttons & 1) === 1
AJ Richardson

我有一种情况,我期望在一次鼠标移动期间我应该使按钮代码为“ 1”,但它会产生“ 7”,-所有工作都在Chrome上进行。有人知道吗
瓦西里大厅

@VasilyHall查看MDN文档MouseEvent.buttons,似乎7意味着它认为“主要”,“次要”和“辅助”按钮都被按下了。我不确定为什么会这样-您使用的是高级鼠标吗?如果是这样,也许值得尝试一个基本的。如果只需要执行该操作,则可以使用按位检查以确保按下了左按钮,而忽略了其他任何按钮。例如。MouseEvent.buttons & 1 === 1
Jono Job)

谢谢您,我在一个特殊的浏览器中使用了我的JavaScript:Adobe Illustrator应用程序中的嵌入式Chrome(ium?)-我敢打赌,所有这些东西的组合会以某种方式导致7,尽管只按下了一个按钮。看到这在我的应用程序中是如何保持一致的,我只是在做1或7的检查以促进交互性。我要补充一点,尽管我确实使用Logitech M570(或任何其他型号)轨迹球鼠标,但它在常规浏览器中正确注册了1,但在Illustrator内部却正确注册了7。
Vasily Hall

16

我认为最好的方法是保留自己的鼠标按钮状态记录,如下所示:

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

+1,谢谢。我以为我可能不得不求助于此,但是我希望有一些功能可以让您直接直接检查状态。
TM。

12
有没有不使用布尔值的原因吗?
moala 2014年

1
@moala我认为Int似乎打字少,最终性能稍好
Johnathan Elmore

12

解决方案不好。可以先在文档上“鼠标下移”,然后在浏览器外“鼠标下移”,在这种情况下,浏览器仍会认为鼠标已按下。

唯一好的解决方案是使用IE.event对象。


11
我知道您来自哪里,但是拥有仅适用于IE的解决方案也不是一个好的解决方案。
TM。

@alfred在某些情况下,可能有助于了解mousemove是否在窗口之外。if(event.target.nodeName.toLowerCase ==='html')down = 0;
2015年

6

我知道这是一篇过时的文章,但是我认为使用鼠标上/下键来跟踪鼠标按钮感觉有些笨拙,因此我找到了一种可能吸引某些人的替代方法。

<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返回的对象中使用可以用作标志的任何内容,而不会破坏页面的外观,例如border-color。

我本想在:active部分中设置自己的用户定义样式,但无法使其正常工作。如果可能的话会更好。


感谢您分享。我曾将这种想法用于拖放式样式逻辑,但在IE上遇到了一个问题,必须包含其他逻辑
Eyup Yusein

4

以下代码段将在document.body中发生mouseDown事件2秒后尝试执行“ doStuff”功能。如果用户抬起按钮,将发生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);
}

谢谢,但这并不是我一直在寻找的行为(尽管我可以看到我的问题如何表明这就是我要做的事情)。
TM。

3

简短而甜美

我不确定为什么以前的答案都不对我有用,但是我在尤里卡的时候提出了这个解决方案。它不仅有效,而且最优雅:

添加到正文标签:

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

然后测试并执行myfunction()是否down等于1

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

4
您是新手,所以我将在这里为您提供一些帮助。首先,请注意帖子中的语法-我可能花了更多的时间来修复它,而不是投入其中。其次,您的解决方案只是上面列出的其他解决方案的另一个版本-并不是什么新鲜事。第三,您的解决方案使用了一种称为“使用标志”的技术,Thomas Hansen在上面建议了这一技术。在张贴到较旧的帖子时,请注意检查语法,不要重复解决方案,而无需提供有关其他解决方案为何对您不起作用的解释。
Zachary Kniebel

5
我没有,但投票您的解决方案了,因为它是有效的,你是新来的SO
扎卡里Kniebel

2

您可以结合使用@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设置为0之前,是否需要在onmouseup()中清除clearInterval()?我对在将其设置为0和停止计时器(将超时时间设置为200)之间触发计时器功能持谨慎态度。同样在onmousedown中。
paxdiablo

clearIntervals的顺序不会改变,因为当前执行线程将在任何事件(包括计时器)触发之前完成。
纳撒尼尔·赖因哈特

2

您需要处理MouseDown和MouseUp并设置一些标记或某些东西来“在以后”跟踪它... :(


2

如果您使用现有的鼠标事件处理程序在一个复杂的页面中工作,建议您在捕获时处理事件(而不是气泡)。为此,只需将的第3个参数设置addEventListenertrue

此外,您可能需要检查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是很重要的b / c,它可以确保仍然记录窗口外的 mouseup事件。


1

使用MouseEvent API检查按下的按钮(如果有):

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

返回

一个代表一个或多个按钮的数字。如果同时按下多个按钮,则将这些值组合在一起(例如,3个为主要+次要)。

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,以下解决方案甚至可以处理“拖动页面然后释放大小写”的情况。

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

我不知道它如何处理多个鼠标按钮。如果有一种方法可以在窗口外部开始单击,然后将鼠标移到窗口中,那么在该窗口中也可能无法正常工作。


0

在jQuery示例下,当鼠标悬停在$('。element')上方时,颜色会根据所按下的鼠标按钮而变化。

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

就像@Jack所说的,当mouseup发生在浏览器窗口之外时,我们不知道它...

这段代码(几乎)对我有用:

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

不幸的是,mouseup在以下情况之一中,我不会获得该事件:

  • 用户同时按下键盘键和鼠标按钮,在浏览器窗口外部释放鼠标按钮,然后释放键。
  • 用户同时按下两个鼠标按钮,然后在浏览器窗口之外释放一个鼠标按钮,然后释放另一个。

-1

好吧,您不能在事件之后检查它是否已关闭,但是您可以检查它是否已启动...如果它已启动..这意味着不再关闭了:P哈哈

因此,用户按下按钮(onMouseDown事件)...之后,您检查按钮是否按下(onMouseUp)。虽然还没有启动,但是您可以做您需要的事情。


2
onMouseUp也不是事件吗?您将如何检查onMouseup的“属性”?还是谁的财产?
罗希特

@Rohit:您不检查属性,而是管理一个标志,指示事件已发生...鼠标按钮向上或向下。
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;
        }

这个跨浏览器的版本对我来说很好用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.