JavaScript習作「MoveBox」


デモページ


 ブラウザで動くJavaScriptデモです。
 画面をクリックすると箱が出ます。しばらくすると勝手に動き出します。
 マウスでドラッグすると動かすことができます。
 ドラッグしながらボタンを離すと放り投げることもできます。


【表示】
 STATUS: fpsと箱の数を表示
 MOUSE: マウスイベントとマウス座標を表示


【設定】
 「設定」の上にマウスも移動すると設定ダイアログが開きます(クリックは不要)
 以下の設定ができます
・目標FPS: タイマーイベントの設定値を指定します。十分な性能があればこの数値に近づきます。
・デモモード:自動的に箱を出現させます。以下の5タイプがあります。
  (無し)
  ランダムに配置
  ランダムに配置(高頻度)
  ランダムに降る
  ランダムに降る(高頻度)
・常に揺らす:チェックを入れると箱が常に揺れるようになります。


【詳細】
・箱は最大100個
・5秒に一度ランダムな方向へ動き始める。移動速度は5秒ごとに速くなる傾向
・画面の外にでると消える(画面サイズはページ表示直後のウィンドウサイズを基準とする)
・ドラッグ中の箱が他の箱にぶつかると押し出す



● 動作環境

 JavaScript対応のWebブラウザで動作します。
 以下の環境で確認しています。


Firefox3.6 @ WindowsXP/7
IE6.0 @ WindowsXP
IE8.0 @ Windows7
Chrome4.0 @ WindowsXP
Macでも動くはず。iPhoneではドラッグが出来ないようです。



● このデモの目的

【多数のキャラ表示】
 imgtest1での実験からjavaScriptで多数のキャラクターを動かす場合の性能のだしかたが分かってきたので、汎用ライブラリをめざしてクラス化の実験です。



 以下の点に留意して作成しました。
・表示するオブジェクトを予め作成しておきDOMで操作する
 →開始時にcreateNodes() 関数で100個ノードを作るようにした。
  ※オブジェクトの実態は style.position = "absolute"; な、Divノードで背景色とサイズを指定して箱(矩形)としています。
  ※作成直後や未使用時は、style.visibility = "hidden"; として非表示にしている。
・操作対象をdocument.getElementByIdした結果を保持しておき、document.getElementByIdの回数を減らす
 →配列m_nodesに格納する。キャラ使用時は、popして取り出し、キャラ消去時にpushして返却する


 設定で「常に揺らす」にチェックをいれると、箱がつねに動くようになりますが、箱が静止しているときより負荷が高いようです。


【マウスイベントの取り扱い】
 マウスドラッグでキャラを動かすようにしました。
 簡単なはずが意外とハマりました。
 箱をドラッグすると、たまにマウスカーソルがWAITカーソルになってしまってドラッグされない。その上、onmouseupが発生しなくて、ドラッグ状態が継続してしまう…
 これについては、「イベント伝搬キャンセル」する必要がありました。
 window.document.onmousedownのイベント中で以下の処理を行います。
Firefox
 if ( event && event.preventDefault ) event.preventDefault();
IE
 return false;で終了する


 まだドラッグ中にマウスが、ウィンドウ外部に出てしまうのは解決していません(IEFirefoxでは問題ない)。
 この記事の方法で対策できるようですが・・・


● プログラムの解説


 ファイルは1つだけですので、「ブラウザのソースを見る」ですべて読むことができます。
 URL: http://labs.dokokano.net/app/webdemo/movebox/movebox.html



iPhone対応のためには…


 iPhone(Safari)では、onmousemoveイベントが発生しないようです。
 タッチパネルなので、タッチしていない状態ではイベントは起こりようがないですが、ドラッグ中は発生するかなぁと期待してたらそうではないみたい。
 その代わり独自拡張のtouch〜系のイベントが新設されているみたいです。
 以下の記事を参考にしました。


iPhoneタッチ機能、ジェスチャ機能のプログラミング方法 - SitePen (マイコミジャーナル)


 こちらはマルチタッチも対応しているようです。
 さすがにこらは実機がないと試せないので、iPod Touchでも買おうかな〜