在浏览器/窗口外捕获鼠标松开事件

13

现在,我正在通过鼠标松开来停止拖动事件,如下所示:

$(document).mouseup(_onMouseUp);

不过当鼠标离开浏览器窗口时,我需要捕获鼠标抬起事件,类似于Flash中的releaseOutside

在JavaScript中是否可能实现?


只有当浏览器被聚焦时,键盘/鼠标事件才能正常工作(除非你使用IE:http://spider.io/blog/2012/12/internet-explorer-data-leakage/)。否则将会是一个巨大的安全漏洞。 - gen_Eric
可以检测到文档失去焦点,就像我在我的答案中详细说明的那样。这可能会实现OP想要的目标。 - Ed Bayiates
4个回答

11

是的,可以在浏览器窗口外捕获mouseup事件。只需在mousedown回调函数中调用Element.setCapture()即可。

记得在mouseup时也要调用document.releaseCapture()

elem.addEventListener('mousedown', function() {
    ...
    elem.setCapture();
});
elem.addEventListener('mouseup', function() {
    ...
    document.releaseCapture();
});

2
FYI,Element.setCapture()在Chrome中尚未得到支持(https://bugs.chromium.org/p/chromium/issues/detail?id=246536)。 - James Clark
是的,但Chrome默认会捕获鼠标吗? - Maciej Chałapuk
2
我不知道,但即使它可以,elem.setCapture() 目前在 Chrome 中会抛出异常,因此仍然需要一些小心。 - James Clark
除非你想在 mouseup 之前释放捕获,否则不需要使用 releaseCapture。请参阅 https://developer.mozilla.org/pl/docs/Web/API/Element/setCapture。 - 1j01
10
MDN 推荐使用 setPointerCapture ,因为它具有更广泛的浏览器支持。它的工作方式与之前差不多,但是需要传递一个指针 ID。您可以从 pointerdown 事件中获取指针 ID,应该将其用于替换 mousedown。我猜指针 ID 可能是用于多点触控界面的——在我的测试中,它似乎总是为 1。 - Patrick Stephansen
在Chrome上对我不起作用。我拖出一张图片,但当我把它放在桌面上时,事件没有被触发。 - YTG

9

您无法在浏览器窗口外部检测到鼠标按下或松开事件,但我认为您想要做的是当用户在浏览器窗口外单击时取消拖放操作。您可以通过对浏览器窗口失去焦点做出反应来实现这一点,例如:

$(window).on("blur", function(e) {
    // Cancel my drag and drop here
});

或者

$(document).on("blur", function(e) {
    // Cancel my drag and drop here
});

这将为您覆盖浏览器窗口外的鼠标点击,以及诸如 Windows Alt+Tab 任务切换之类的操作。

我猜应该用 window 而不是 document,参见 http://www.quirksmode.org/dom/events/blurfocus.html - Ali Shakiba
我已在所有5个主要的浏览器和多种设备上测试了“document”。但是,你也可以使用“window”,它也能正常工作。 - Ed Bayiates

8

在每个主要的浏览器中,您都可以捕获浏览器窗口外的mouseup事件:Chrome、Edge和Firefox。

您只需要像这样将侦听器附加到“window”对象

window.addEventListener('mouseup', 
                         () => console.log('mouse up captured outside the window'));

https://codepen.io/fredrikborgstrom/pen/vRBaZw

或者在您的情况下,使用jQuery,它会是这样的:

$(window).mouseup(_onMouseUp);

在Chrome上它对我不起作用。我拖出一张图片,但当我把它放在桌面上时,事件没有被触发。 - YTG
如果你正在进行拖放操作,那么可以这样做: window.addEventListener("dragend", () => console.log('drag end event caught')); 如果在浏览器窗口外面放置,则此方法有效。 - Fredrik_Borgstrom

6
可以像下面这样捕获浏览器窗口外的鼠标松开事件:
elem.addEventListener('mousedown', function(e) {
    ...
    elem.setPointerCapture(e.pointerId);
});
elem.addEventListener('mouseup', function(e) {
    ...
    elem.releasePointerCapture(e.pointerId);
});

参考文献: setPointerCapture releasePointerCapture


在Chrome上对我不起作用。我拖出一张图片,但当我把它放在桌面上时,事件没有被触发。 - YTG
我认为你必须使用事件指针(pointerdown, pointermove和pointerup),而不是mousedown,mouseup等,才能获取pointerId。它们看起来可以互换使用:https://dev59.com/zcLra4cB1Zd3GeqPPLBs - dallin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接