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

TM.*_*TM. 127 javascript mouse input-devices user-input input

有没有办法检测JavaScript中当前是否有鼠标按钮?

我知道"mousedown"事件,但这不是我需要的.按下鼠标按钮一段时间后,我希望能够检测到它是否仍然按下.

这可能吗?

Eug*_*kin 137

关于Pax的解决方案:如果用户有意或无意地点击多个按钮,它就不起作用.不要问我怎么知道:-(.

正确的代码应该是这样的:

var mouseDown = 0;
document.body.onmousedown = function() { 
  ++mouseDown;
}
document.body.onmouseup = function() {
  --mouseDown;
}
Run Code Online (Sandbox Code Playgroud)

通过这样的测试:

if(mouseDown){
  // crikey! isn't she a beauty?
}
Run Code Online (Sandbox Code Playgroud)

如果你想知道按下了什么按钮,请准备好使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;
}
Run Code Online (Sandbox Code Playgroud)

现在您可以检查完全按下了哪些按钮:

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!
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在要注意上面的代码只适用于符合标准的浏览器,它们会传递一个从0开始的按钮编号.IE使用当前按下按钮的位掩码:

  • 0表示"没有按下"
  • 左边1
  • 2为对
  • 中间4
  • 以及上面的任何组合,例如,5为左+中

所以相应地调整你的代码!我把它留作练习.

请记住:IE使用名为..."event"的全局事件对象.

顺便说一句,IE有一个在你的情况下有用的功能:当其他浏览器仅为鼠标按钮事件(onclick,onmousedown和onmouseup)发送"按钮"时,IE也会发送它与onmousemove.因此,当您需要知道按钮状态时,您可以开始侦听onmousemove,并在获得后立即检查evt.button - 现在您知道按下了哪些鼠标按钮:

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

当然,如果她玩死了而不动,你什么都得不到.

相关链接:

更新#1:我不知道为什么我继承了document.body风格的代码.最好将事件处理程序直接附加到文档中.

  • 我认为这在Chrome中不起作用,因为如果原始mousedown发生在滚动条上,则Chrome不会生成鼠标事件.[示例](http://www.pmarks.net/posted_links/chromium_up_down_bug.html),来自[此Chrome/Chromium问题](http://code.google.com/p/chromium/issues/detail?id = 14204).因此,如果有人使用滚动条,您的鼠标左键将永远停止!(在Chrome中) (5认同)
  • 我不明白为什么你在第二个例子中增加mousedown数组elts.为什么每个按钮的计数器而不是每个按钮的bool? (5认同)
  • 我喜欢你的解决方案,但是如果鼠标来自不同的应用程序(例如 ms word 并拖动一些文本)怎么办?如何检测鼠标已按下? (3认同)
  • 我感觉这个答案有很大的问题。如果您单击向下然后在窗口外释放,_或者根本单击鼠标右键,_ mouseup 将不会被触发,您的值将卡在大于 0 的位置,并且您的检查将永久失败。 (3认同)
  • 这是一个非常受欢迎的问题(和答案).我很惊讶这还没有出现,但你根本不需要存储鼠标数据.您可以将`event.buttons`插入到您正在使用的任何事件触发器中,而无需外部保存的变量.我问了一个全新的问题(因为我的mouseup事件并不总是触发,所以这个解决方案对我不起作用)并且在5分钟内完成了答案. (2认同)

Jon*_*Job 25

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

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

  • 适用于所有现代浏览器(Safari除外)使用 MouseEvent.buttons
  • 对于Safari,请使用MouseEvent.which(对于Safari,buttons将不会定义)注意:对于右键和中键点击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;
Run Code Online (Sandbox Code Playgroud)

如果需要更复杂的场景(不同的按钮/多个按钮/控制键),请查看MouseEvent文档.当/如果Safari提升游戏时,这将变得更容易.

  • 此代码检查是否仅按下主按钮并要求所有其他按钮未按下.(例如,如果按下主要和次要,则"e.buttons"将为"1 + 2 = 3",因此"e.buttons === 1"将为假).如果要检查主按钮是否已关闭,但不关心任何其他按钮状态,请执行以下操作:`(e.buttons&1)=== 1` (5认同)

pax*_*blo 17

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

var mouseDown = 0;
document.body.onmousedown = function() { 
    mouseDown = 1;
}
document.body.onmouseup = function() {
    mouseDown = 0;
}
Run Code Online (Sandbox Code Playgroud)

然后,在你的代码中:

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

  • 是否有理由不使用布尔值? (11认同)
  • @moala 我认为 Int 似乎打字更少,最终性能稍好:http://jsperf.com/bool-vs-int (2认同)

小智 12

解决方案并不好.一个人可以在文档上"mousedown",然后在浏览器外面"mouseup",在这种情况下,浏览器仍然会认为鼠标已关闭.

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

  • 我看到你来自哪里,但拥有一个仅适用于IE的解决方案也不是一个好的解决方案. (9认同)

Mar*_*tin 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>
Run Code Online (Sandbox Code Playgroud)

:主动选择器比鼠标向上/向下处理鼠标点击要好得多,你只需要在onmousemove事件中读取该状态的方法.为此我需要作弊并依赖于默认光标为"auto"的事实,我只是将其更改为"default",这是默认情况下自动选择的.

您可以使用getComputedStyle返回的对象中的任何内容,您可以将其用作标记,而不会破坏页面的外观,例如border-color.

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


Mic*_*man 6

如果您正在使用现有鼠标事件处理程序的复杂页面中工作,我建议在捕获时处理事件(而不是冒泡)。为此,只需将 的第三个参数设置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);
Run Code Online (Sandbox Code Playgroud)

将处理程序添加到文档(或窗口)而不是 document.body 很重要,因为它可以确保仍然记录窗口外部的mouseup 事件。


NVR*_*VRM 5

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

// Mouse buttons
document.addEventListener('mousedown', e => console.log(e.buttons))
// Keyboard keys
document.addEventListener('keydown', e => console.log(e.key))
Run Code Online (Sandbox Code Playgroud)

返回

代表一个或多个按钮的数字。对于同时按下的多个按钮,这些值将被合并(例如,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)
Run Code Online (Sandbox Code Playgroud)


小智 5

如果其他人遇到这种情况,您可以.matches:active选择器一起使用:

function mouseDown() {
    return document.body.matches(":active");
}
Run Code Online (Sandbox Code Playgroud)