在IE浏览器窗口之外响应onmousemove事件

在Internet Explorer 7中, 正文onmousemovedocument.onmousemove事件只在鼠标位于浏览器窗口内时触发,而不是在外面。 然而在Firefox中,当我移出浏览器窗口时,onmousemove事件被正确调用。

我如何设置IE浏览器窗口以外的事件?

谷歌地图在IE中这样做。 如果按住鼠标button并将鼠标移动到浏览器窗口外,则可以看到地图仍然移动。

(注意:这个回答专指mousedown -> mousemove -> mouseup的“标准”拖拽实现mousedown -> mousemove -> mouseup ,不适用于HTML5拖拽规范 )。

允许在浏览器窗口之外拖动是两个不同的浏览器已经解决的老问题。

除了IE之外,当用户通过浏览器启动拖动操作时,浏览器已经做了一些简单的事情(这一切都只是从观察而已):一种状态机开始处理窗口外的鼠标移动的特殊情况:

  1. 用户触发document内的mousedown事件
  2. 用户触发mousemove事件。 即使从document外部触发事件也会触发(即窗口)
  3. 用户触发mouseup事件( document内部或外部)。 从文档外部触发的mousemove事件不再触发

IE和旧版本的Firefox [迟至2.0.20]不会出现这种行为。 在窗口外面拖动不起作用1

IE和FF2的问题实际上在于一个元素是否是“可select的”(参见这里和这里 )。 如果拖动实现不执行任何操作(从而允许通过鼠标进行select),则所述实现不必考虑窗外的移动; 浏览器将继续,并正确地触发mousemove ,并允许用户在窗外自由拖动。 尼斯。

然而,通过让浏览器决定在mousemove上做什么,你会得到这样的效果,浏览器认为用户试图“select”某些东西(如元素),而不是移动它,然后疯狂地尝试突出显示元素或当鼠标在拖动过程中穿过元件进入或离开元件时在其中的文字。

我见过的大多数拖拽实现都做了一些小技巧,让元素被拖拽为“不可选”,从而完全控制了mousemove来模拟拖拽:

 elementToDrag.unselectable = "on"; elementToDrag.onselectstart = function(){return false}; elementToDrag.style.userSelect = "none"; // w3c standard elementToDrag.style.MozUserSelect = "none"; // Firefox 

这很好地工作, 但打破了窗外的拖动2

无论如何 ,要回答你的问题,为了让IE(所有版本)允许在窗口外面拖动,使用setCapture (并且释放鼠标时反向释放setCapture )。

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Simple drag demo</title> <style> #dragme { position:absolute; cursor:move; background:#eee; border:1px solid #333; padding:10px; } </style> <script> function makeDraggable(element) { /* Simple drag implementation */ element.onmousedown = function(event) { document.onmousemove = function(event) { event = event || window.event; element.style.left = event.clientX + 'px'; element.style.top = event.clientY + 'px'; }; document.onmouseup = function() { document.onmousemove = null; if(element.releaseCapture) { element.releaseCapture(); } }; if(element.setCapture) { element.setCapture(); } }; /* These 3 lines are helpful for the browser to not accidentally * think the user is trying to "text select" the draggable object * when drag initiation happens on text nodes. * Unfortunately they also break draggability outside the window. */ element.unselectable = "on"; element.onselectstart = function(){return false}; element.style.userSelect = element.style.MozUserSelect = "none"; } </script> </head> <body onload="makeDraggable(document.getElementById('dragme'))"> <div id="dragme">Drag me (outside window)</div> </body> </html> 

演示可以在这里看到 。

这正是谷歌地图所做的事情(正如我在2004年谷歌地图反向工程首次发布时发现的那样)。


1 我相信它实际上只有在文本节点上启动拖动操作(即mousedown )时才会中断。 元素/容器节点不具有相同的行为,可以在文档内部或外部拖动,只要用户在元素的“空白”部分隐藏

2 再次,在文本节点上进行拖动启动。

你可以看看这里的代码,因为它似乎在IE8和FF3.5工作。 如果你能理解他的代码很好。 http://www.walterzorn.de/en/dragdrop/dragdrop_e.htm