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

IT技术 javascript input mouse user-input input-devices
2021-01-13 13:33:17

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

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

这可能吗?

6个回答

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

顺便说一句,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!
  }
};

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

相关链接:

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

经过测试,似乎 evt.button 实际上不存在 onmousemove 与 IE7 ...
2021-03-19 13:33:17
我认为这在 Chrome 中不起作用,因为如果原始 mousedown 发生在滚动条上,Chrome 不会生成 mouseup 事件。一个例子,来自这个 Chrome/Chromium 问题因此,如果有人使用滚动条,您的鼠标左键将永远处于按下状态!(在 Chrome 中)
2021-03-24 13:33:17
这是一个非常受欢迎的问题(和答案)。我很惊讶这还没有出现,但是您根本不需要存储鼠标数据。您可以插入event.buttons正在使用的任何事件触发器,而无需外部保存的变量。我问了一个全新的问题(因为我的 mouseup 事件并不总是触发,所以这个解决方案对我不起作用)并在大约 5 分钟内得到了答案。
2021-04-06 13:33:17
我不明白你为什么在第二个例子中增加 mousedown 数组 elts 。为什么每个按钮都有一个计数器而不是每个按钮的布尔值?
2021-04-08 13:33:17
我喜欢你的解决方案,但如果鼠标来自不同的应用程序,请说 ms word 并拖动一些文本。您将如何检测鼠标已按下?
2021-04-11 13:33:17

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

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

  • 对于所有现代浏览器(Safari 除外),请使用 MouseEvent.buttons
  • 对于 Safari,使用MouseEvent.which对于 Safaributtons将是未定义的) 注意: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 提升它的游戏,这应该会变得更容易。

我有一种情况,我期望在鼠标移动期间我应该让按钮代码为“1”,但它会产生“7”, - 所有工作都在 Chrome 上进行。有人有什么想法吗?
2021-03-15 13:33:17
@VasilyHall 查看 的 MDN 文档MouseEvent.buttons,这似乎7意味着它认为主要、次要和辅助按钮都被按下在一起。我不确定为什么会出现这种情况 - 您使用的是高级鼠标吗?如果是这样,也许值得尝试一个基本的。如果您只是需要让它继续运行,您可以使用按位检查来确保按下左按钮并忽略任何其他按钮。例如。MouseEvent.buttons & 1 === 1.
2021-03-18 13:33:17
此代码检查是否仅按下了主按钮并要求取消按下所有其他按钮。(例如,如果primary 和secondary 都被按下,e.buttonswill be 1+2=3,所以e.buttons === 1是false)。如果您想检查主按钮是否关闭,但不关心任何其他按钮状态,请执行以下操作:(e.buttons & 1) === 1
2021-03-23 13:33:17
另一个例子说明为什么最好从下往上阅读 Stack Overflow 页面。
2021-04-02 13:33:17
谢谢,我在一个特殊的浏览器中使用了我的 JavaScript:Adobe Illustrator 应用程序中的嵌入式 Chrome(ium?) - 我敢打赌所有各种事物的组合以某种方式导致 7,尽管只是按下了一个按钮. 看看这在我的应用程序中是如何保持一致的,我只是检查 1 或 7 以促进我的交互。我要补充的是,虽然我确实使用了 Logitech M570(或其他)轨迹球鼠标,但它在常规浏览器中正确注册了 1,但在 Illustrator 中正确注册了 7。
2021-04-11 13:33:17

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

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.
}
是否有理由不使用布尔值?
2021-03-21 13:33:17
+1,谢谢。我想我可能不得不求助于这个,但我希望有一些功能可以让你直接检查状态。
2021-03-25 13:33:17
@moala 我认为 Int 似乎打字更少,最终性能略好:jsperf.com/bool-vs-int
2021-03-25 13:33:17

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

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

@alfred 在某些情况下,了解 mousemove 是否在窗口外可能会有所帮助。如果(event.target.nodeName.toLowerCase==='html')down=0;
2021-03-22 13:33:17
我知道您来自哪里,但是拥有仅适用于 IE 的解决方案也不是一个好的解决方案。
2021-03-27 13:33:17

我知道这是一篇旧帖子,但我认为使用鼠标向上/向下跟踪鼠标按钮感觉有点笨拙,所以我找到了一个可能吸引某些人的替代方法。

<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 返回的对象中的任何内容,您可以将其用作标志而不会影响页面的外观,例如边框颜色。

我本来希望在 :active 部分设置我自己的用户定义样式,但我无法让它工作。如果可以的话就更好了。

感谢分享这个。我将这个想法用于拖放样式逻辑,但在 IE 上遇到了问题,不得不包含额外的逻辑
2021-04-03 13:33:17