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

时间:2009-11-06 04:01:23

标签: javascript internet-explorer javascript-events

在Internet Explorer 7中, body onmousemove document.onmousemove 事件似乎只在鼠标位于浏览器窗口内时触发,而不是在外部时触发。然而在Firefox中,当我移出浏览器窗口时,会正确调用onmousemove事件。

如何在IE浏览器窗口外设置要调用的事件?

Google Maps在IE中执行此操作。如果按住鼠标按钮并将鼠标移动到浏览器窗口之外,则可以看到地图仍在移动。

2 个答案:

答案 0 :(得分:63)

(注意:此答案仅指mousedown -> mousemove -> mouseup的“标准”拖动实施。它不适用于HTML5 drag specification

允许在浏览器窗口外拖动是一个老问题,不同的浏览器以两种方式解决了这个问题。

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

  1. 用户在mousedown
  2. 中触发document事件
  3. 用户触发mousemove事件。即使从document(即窗口)外部触发,事件也会触发
  4. 用户触发mouseup事件(document内部或外部)。从文档外部触发的mousemove事件不再触发
  5. IE和旧版本的Firefox [最晚为2.0.20]不会出现此行为。在窗口外拖动不起作用 1

    IE和FF2的问题实际上在于元素是否“可选”(参见herehere)。如果拖动实现什么都不做(从而允许鼠标选择),那么所述实现不必考虑窗口外的移动;浏览器将继续并正确触发mousemove,并允许用户在窗口外自由拖动。好的。

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

    我见过的大多数拖拽实现都会让元素被拖动“无法选择”,从而完全控制mousemove来模拟拖动:

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

    这很好用,但在窗外拖动 2

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

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

    Demo can be seen here

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


    1 我相信它实际上只在文本节点上启动拖动操作(即mousedown)时才会中断。元素/容器节点不会表现出相同的行为,并且可以在文档内部或外部拖动,前提是用户在元素的“空”部分进行了鼠标

    2 再次,对于文本节点的拖动启动。

答案 1 :(得分:2)

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