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

发布于 2024-07-09 15:11:40 字数 122 浏览 19 评论 0原文

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

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

这可能吗?

Is there a way to detect if a mouse button is currently down in JavaScript?

I know about the "mousedown" event, but that's not what I need. Some time AFTER the mouse button is pressed, I want to be able to detect if it is still pressed down.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

两仪 2024-07-16 15:11:40

关于 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!
  }
};

当然,如果她装死,您什么也得不到。没有移动。

相关链接:

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

Regarding Pax' solution: it doesn't work if user clicks more than one button intentionally or accidentally. Don't ask me how I know :-(.

The correct code should be like that:

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

With the test like this:

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

If you want to know what button is pressed, be prepared to make mouseDown an array of counters and count them separately for separate buttons:

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

Now you can check what buttons were pressed exactly:

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

Now be warned that the code above would work only for standard-compliant browsers that pass you a button number starting from 0 and up. IE uses a bit mask of currently pressed buttons:

  • 0 for "nothing is pressed"
  • 1 for left
  • 2 for right
  • 4 for middle
  • and any combination of above, e.g., 5 for left + middle

So adjust your code accordingly! I leave it as an exercise.

And remember: IE uses a global event object called … "event".

Incidentally IE has a feature useful in your case: when other browsers send "button" only for mouse button events (onclick, onmousedown, and onmouseup), IE sends it with onmousemove too. So you can start listening for onmousemove when you need to know the button state, and check for evt.button as soon as you got it — now you know what mouse buttons were pressed:

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

Of course you get nothing if she plays dead and not moving.

Relevant links:

Update #1: I don't know why I carried over the document.body-style of code. It will be better to attach event handlers directly to the document.

春风十里 2024-07-16 15:11:40

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

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

  • 对于所有现代浏览器(包括 Safari v11.1+ [iOS 上的 v11.3+]),请使用 MouseEvent.buttons 对于 Safari MouseEvent.buttons
  • 对于 Safari MouseEvent.buttons 11.1(iOS 上为 11.3),使用 MouseEvent.which< /code>(对于 Safari,buttons 未定义)注意:which 使用与 buttons 不同的数字来进行右键单击和中键单击。

当在 document 上注册时,一旦光标重新进入浏览器,mousemove 就会立即触发,因此如果用户在外部释放鼠标,那么一旦鼠标返回,状态就会更新里面。

一个简单的实现可能如下所示:

var primaryMouseButtonDown = false;

function setPrimaryButtonState(e) {
  var flags = e.buttons !== undefined ? e.buttons : e.which;
  primaryMouseButtonDown = (flags & 1) === 1;
}

document.addEventListener("mousedown", setPrimaryButtonState);
document.addEventListener("mousemove", setPrimaryButtonState);
document.addEventListener("mouseup", setPrimaryButtonState);

该代码跟踪鼠标主按钮(通常是左侧)的状态,忽略其他鼠标按钮的状态。

如果需要更复杂的场景(不同的按钮/多个按钮/控制键),请查看 MouseEvent 文档。

This is an old question, and the answers here seem to mostly advocate for using mousedown and mouseup to keep track of whether a button is pressed. But as others have pointed out, mouseup will only fire when performed within the browser, which can lead to losing track of the button state.

However, MouseEvent (now) indicates which buttons are currently pushed:

  • For all modern browsers (including Safari v11.1+ [v11.3+ on iOS]), use MouseEvent.buttons
  • For Safari < 11.1 (11.3 on iOS), use MouseEvent.which (buttons will be undefined for Safari) Note: which uses different numbers from buttons for Right and Middle clicks.

When registered on document, mousemove will fire immediately as soon as the cursor reenters the browser, so if the user releases outside then the state will be updated as soon as they mouse back inside.

A simple implementation might look like:

var primaryMouseButtonDown = false;

function setPrimaryButtonState(e) {
  var flags = e.buttons !== undefined ? e.buttons : e.which;
  primaryMouseButtonDown = (flags & 1) === 1;
}

document.addEventListener("mousedown", setPrimaryButtonState);
document.addEventListener("mousemove", setPrimaryButtonState);
document.addEventListener("mouseup", setPrimaryButtonState);

That code tracks the state of the primary mouse button (typically the left), ignoring the state of other mouse buttons.

If more complicated scenarios are required (different buttons/multiple buttons/control keys), check out the MouseEvent docs.

雪落纷纷 2024-07-16 15:11:40

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

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

I think the best approach to this is to keep your own record of the mouse button state, as follows:

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

and then, later in your code:

if (mouseDown == 1) {
    // the mouse is down, do what you have to do.
}
心房的律动 2024-07-16 15:11:40

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

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

the solution isn't good.
one could "mousedown" on the document, then "mouseup" outside the browser, and on this case the browser would still be thinking the mouse is down.

the only good solution is using IE.event object.

瀞厅☆埖开 2024-07-16 15:11:40

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

<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 部分设置我自己的用户定义样式,但我无法让它工作。 如果可以的话就更好了。

I know this is an old post, but I thought the tracking of mouse button using mouse up/down felt a bit clunky, so I found an alternative that may appeal to some.

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

The :active selector handles the mouse click much better than mouse up/down, you just need a way of reading that state in the onmousemove event. For that I needed to cheat and relied on the fact that the default cursor is "auto" and I just change it to "default", which is what auto selects by default.

You can use anything in the object that is returned by getComputedStyle that you can use as a flag without upsetting the look of your page e.g. border-color.

I would have liked to set my own user defined style in the :active section, but I couldn't get that to work. It would be better if it's possible.

韶华倾负 2024-07-16 15:11:40

如果您正在使用现有鼠标事件处理程序的复杂页面中工作,我建议在捕获上处理事件(而不是冒泡)。 为此,只需将 addEventListener 的第三个参数设置为 true 即可。

此外,您可能需要检查 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 中很重要,因为它可以确保仍然记录窗口外部的 mouseup 事件

If you're working within a complex page with existing mouse event handlers, I'd recommend handling the event on capture (instead of bubble). To do this, just set the 3rd parameter of addEventListener to true.

Additionally, you may want to check for event.which to ensure you're handling actual user interaction and not mouse events, e.g. 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);

Add the handler to document (or window) instead of document.body is important b/c it ensures that mouseup events outside of the window are still recorded.

苄①跕圉湢 2024-07-16 15:11:40

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

function mouseDown() {
    return document.body.matches(":active");
}

In case someone else runs into this, you can use .matches with the :active selector:

function mouseDown() {
    return document.body.matches(":active");
}
殊姿 2024-07-16 15:11:40

以下代码片段将在 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);
}

The following snippet will attempt to execute the "doStuff" function 2 seconds after the mouseDown event occurs in document.body. If the user lifts up the button, the mouseUp event will occur and cancel the delayed execution.

I'd advise using some method for cross-browser event attachment - setting the mousedown and mouseup properties explicitly was done to simplify the example.

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);
}
天暗了我发光 2024-07-16 15:11:40

使用 MouseEvent api,检查按下的按钮,如果任何:

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

返回

代表一个或多个按钮的数字。 对于多个按钮
同时按下,这些值将被组合(例如,3 是主要的 +
中学)。

0 : 无按钮或未初始化 
  1:主按钮(通常是左侧按钮) 
  2:辅助按钮(通常是右侧按钮) 
  4:辅助按钮(一般为鼠标滚轮按钮或中键) 
  8:第四个按钮(通常是“浏览器后退”按钮) 
  16:第五个按钮(通常是“浏览器前进”按钮) 
  

Using the MouseEvent api, to check the pressed button, if any:

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

Return:

A number representing one or more buttons. For more than one button
pressed simultaneously, the values are combined (e.g., 3 is primary +
secondary).

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)
没有伤那来痛 2024-07-16 15:11:40

您可以结合@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
}

You can combine @Pax and my answers to also get the duration that the mouse has been down for:

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

Then later:

if (mousedown >= 2000) {
  // do something if the mousebutton has been down for at least 2 seconds
}
感受沵的脚步 2024-07-16 15:11:40

您需要处理 MouseDown 和 MouseUp 并设置一些标志或其他东西来跟踪它“稍后”......:(

You need to handle the MouseDown and MouseUp and set some flag or something to track it "later down the road"... :(

明天过后 2024-07-16 15:11:40

简短而甜蜜,

我不确定为什么以前的答案都不适合我,但我突然想到了这个解决方案。 它不仅有效,而且非常优雅:

添加到 body 标记:

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

如果 down 等于 1,则测试并执行 myfunction()

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

Short and sweet

I'm not sure why none of the previous answers worked for me, but I came up with this solution during a eureka moment. It not only works, but it is also most elegant:

Add to body tag:

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

Then test and execute myfunction() if down equals 1:

onmousemove="if (down==1) myfunction();"
↘人皮目录ツ 2024-07-16 15:11:40

使用 jQuery,以下解决方案甚至可以处理“拖出页面然后释放的情况”。

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

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

Using jQuery, the following solution handles even the "drag off the page then release case".

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

I don't know how it handles multiple mouse buttons.
If there were a way to start the click outside the window, then bring the mouse into the window, then this would probably not work properly there either.

旧时光的容颜 2024-07-16 15:11:40

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

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

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

不幸的是,我不会得到 mouseup其中一种情况会发生 事件:

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

As said @Jack, when mouseup happens outside of browser window, we are not aware of it...

This code (almost) worked for me:

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

Unfortunately, I won't get the mouseup event in one of those cases:

  • user simultaneously presses a keyboard key and a mouse button, releases mouse button outside of browser window then releases key.
  • user presses two mouse buttons simultaneously, releases one mouse button then the other one, both outside of browser window.
原谅我要高飞 2024-07-16 15:11:40
        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;
        }

这个跨浏览器版本对我来说效果很好。

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

this cross-browser version works fine for me.

笑叹一世浮沉 2024-07-16 15:11:40

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

Below jQuery example, when mouse is over $('.element'), color is changing depending on which mouse button is pressed.

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();
});
勿忘初心 2024-07-16 15:11:40

好吧,您无法在事件发生后检查它是否已按下,但您可以检查它是否已按下...如果它已按下...则意味着不再按下:P lol

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

Well, you can't check if it's down after the event, but you can check if it's Up... If it's up.. it means that no longer is down :P lol

So the user presses the button down (onMouseDown event) ... and after that, you check if is up (onMouseUp). While it's not up, you can do what you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文