2010年10月26日火曜日

mousemoveイベントのブラウザごとの違い(IE&ChromeとFirefox)

マウスポインタをちょっと愛らしくしたい、なんて仕事がたまにあると思う。画像を変えて、マウスに少し遅れて追従するような動きをさせる、とか。

例えば以下のサイトのように。

これらのサイトをいろいろなブラウザで閲覧して気づいたのだが、Firefoxはほかと挙動が違う。具体的には、ページを読み込んでからマウスを動かすまで、マウスポインタに画像が追従しない。試しにFirefoxでリロードしてからマウスを動かさずにただ眺めてみよう。

これがなぜなのか少し試行錯誤してみたところ、Firefoxだけは人が実際にマウスを動かすまでは有効なmousemoveイベントオブジェクト(= clientXなどの座標値が正しくセットされたmousemoveイベントオブジェクト)が発生しないからのようだ。反対に、Firefox以外の場合は何もしなくても mousemoveイベントが定期的に発生するため、適当なタイミングでその座標値を取得し、画像を設定した要素のスタイル(position:top, position:left)を書き換えることで画像をマウスのところまで移動させることができる。

実験として次のようなhtml+スクリプトを読み込んでみる(jQuery利用)。マウスを動かさずにじっとしていれば、ブラウザの違いが確認できる。

<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(function(){
  var cnt = 0;
  function f(e){
    $('#info').text(cnt + ' : ' + e.clientY);
    cnt++;
  };
  // mousemoveイベントに上の関数をバインド
  $('body').mousemove(f);
});
</script>
</head>
<body>
<p id="info"></p>
</body>
</html>
IE, Chrome の場合は、
ロードしただけでmousemoveが定期的に発生(カウンタ表示が1秒ごとくらいに増えていく。マウスを動かしていないのに…)
したがってマウス座標(mousemoveイベントオブジェクトのclientYプロパティ)が取得できる
Firefox(3.6)の場合は、
待っていても mousemove が発生しない。座標が取れない。

待ってもイベントが発生しないのであれば、強制的に発生させてみたらどうか? そこで、上のスクリプトを1行だけ変えてtrigger()を追加してみる。

(略)
  // mousemoveイベントに上の関数をバインド。さらにtrigger()で強制的にイベントを発生させる
  $('body').mousemove(f).trigger("mousemove");
});
</script>
(略)
この結果は、
0 : undefined と表示されて終了。triggerで発生させたイベントオブジェクトには座標値がセットされないらしい。

というわけでFirefoxの場合だけ、マウスが動くまでマウス用画像は座標(0, 0)の位置で待機するという仕様になりました…

0 件のコメント:

コメントを投稿