web-dev-qa-db-ja.com

IE)のブラウザウィンドウの外でonmousemoveイベントに応答する

Internet Explorer 7body onmousemoveまたはdocument.onmousemoveイベントでは、マウスがブラウザウィンドウの外側にあるときではなく、ブラウザウィンドウの内側にあるときに起動します。しかし、Firefoxでは、ブラウザウィンドウの外に移動すると、onmousemoveイベントが正しく呼び出されます。

IEのブラウザウィンドウの外部で呼び出されるようにイベントを設定するにはどうすればよいですか?

Google Maps IEでこれを行います。マウスボタンを押したままブラウザウィンドウの外にマウスを移動すると、マップがまだ移動していることがわかります。

26
Matthew Lock

(注:この回答は、mousedown -> mousemove -> mouseupの「標準」ドラッグ実装のみを参照しています。 HTML5ドラッグ仕様 には適用されません)。

ブラウザウィンドウの外側へのドラッグを許可することは、さまざまなブラウザが2つの方法で解決した古い問題です。

IEを除いて、ユーザーがmousedownを介してドラッグ操作を開始すると、ブラウザーは適切な処理を実行します(これはすべて観察によるものです)。一種のステートマシンが起動して、外部でのマウスの動きの特殊なケースを処理します。窓:

  1. ユーザーがmousedown内でdocumentイベントをトリガーします
  2. ユーザーがmousemoveイベントをトリガーします。 document(つまりウィンドウ)の外部からトリガーされた場合でも、イベントが発生します
  3. ユーザーがmouseupイベントをトリガーします(documentの内部または外部)。ドキュメントの外部からトリガーされたmousemoveイベントは発生しなくなりました

IE以前のバージョンのFirefox [2.0.20まで]はこの動作を示しません。ウィンドウの外にドラッグしても機能しません1

IEおよびFF2の問題は、実際には要素が「選択可能」であるかどうかにあります( ここ および ここ を参照)。実装のドラッグは何もしません(したがって、マウスによる選択が可能になります)。その場合、実装はウィンドウの外側の動きを考慮する必要はありません。ブラウザは先に進み、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>

デモはここで見ることができます

これはまさにグーグルマップが行うことです(グーグルマップが最初にリリースされた2004年にリバースエンジニアリングされて以来発見したように)。


1実際には、テキストノードでドラッグ操作(つまり、mousedown)を開始したときにのみ壊れると思います。要素/コンテナノードは同じ動作を示さず、ユーザーが要素の「空の」部分をマウスで下に移動した場合、ドキュメントの内側または外側をドラッグできます。

2繰り返しますが、テキストノードでのドラッグ開始の場合。

66
Crescent Fresh

IE8とFF3.5で動作するように見えるので、ここでコードを見ることができます。あなたが彼のコードをよく理解できれば。 http://www.walterzorn.de/en/dragdrop/dragdrop_e.htm

2
James Black