(注意:这个答案专门指的是“标准”拖动实现mousedown -> mousemove -> mouseup
。它不适用于HTML5拖动规范 http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html).
允许拖动到浏览器窗口之外是一个老问题,不同的浏览器通过两种方式解决了这个问题。
除 IE 外,当用户通过以下方式发起拖动操作时mousedown
浏览器做了一些巧妙的事情(这一切都只是来自观察):一种状态机启动来处理窗口外鼠标移动的特殊情况:
- 用户触发器
mousedown
内的事件document
- 用户触发器
mousemove
事件。事件触发即使从外部触发document
(即窗户)
- 用户触发器
mouseup
事件(内部或外部document
). mousemove
从文档外部触发的事件不再火
IE and older versions of Firefox [as late as 2.0.20] don't exhibit this behavior. Dragging outside the window just doesn't work1.
IE 和 FF2 的问题实际上在于元素是否“可选择”(参见here https://developer.mozilla.org/En/CSS/-moz-user-select and here http://msdn.microsoft.com/en-us/library/ms534706(VS.85,loband).aspx)。如果拖动实现不执行任何操作(从而允许通过鼠标进行选择),则所述实现不必考虑窗口外的移动;浏览器将继续并触发mousemove
正确地并且允许用户在窗口之外自由拖动。好的。
然而,通过让浏览器决定在 mousemove 上做什么,您会得到这样的效果:浏览器认为用户正在尝试“选择”某些内容(例如元素),而不是移动它,并继续疯狂地尝试突出显示该元素或当鼠标在拖动过程中移入或移出元素时,其中的文本。
我见过的大多数拖动实现都会采取一些技巧来使被拖动的元素“不可选择”,从而完全控制mousemove
模拟拖动:
elementToDrag.unselectable = "on";
elementToDrag.onselectstart = function(){return false};
elementToDrag.style.userSelect = "none"; // w3c standard
elementToDrag.style.MozUserSelect = "none"; // Firefox
This works nicely, but breaks dragging outside the window. 2
Anyway,要回答您的问题,要让 IE(所有版本)允许拖动到窗口外,请使用setCapture http://msdn.microsoft.com/en-us/library/ms536742(VS.85,loband).aspx(反之亦然releaseCapture http://msdn.microsoft.com/en-us/library/ms536689(VS.85,loband).aspx当鼠标被释放时)。
<!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>
演示可以在这里看到 http://jsbin.com/ifuma#noedit.
这正是谷歌地图所做的(正如我在 2004 年首次发布谷歌地图时对谷歌地图进行逆向工程以来发现的那样)。
1I believe it actually only breaks when initiating a drag operation (i.e. mousedown
) on a textnode. Element/container nodes do not exhibit the same behavior and can be dragged around inside or outside the document, provided the user moused down on an "empty " portion of the element
2Again, for drag initiations on textnodes.