fc2ブログ

HTML5 Canvas + jQuery でドラッグ&ドロップ

タイトルのとおり、drag&drop を HTML5 Canvasで実装してみた。
こちらで公開しています → HTML5 Canvasでドラッグ&ドロップ
スタートボタンを押して実行してください。
実装してみてわかったことを簡単に解説する。

1. ソースコード
作成したソースコードは以下のとおり。jQuery は ver1.4.2 を使用。
・html および共通の Canvas 描画クラス
dtest.html  dtestcom.js
・drag&drop処理(1px 移動するごとに Canvas 更新)
dtest1.js
・drag&drop処理(1/24秒ごとに Canvas 更新)
dtest2.js

2. Canvas 更新方法について
「mousemove イベントが発生するたび更新」 → 「1px 移動するごとに更新」 → 「1/24秒ごとに更新」 の順にCPU負荷が小さくなる。

1) 1px 移動するごとに Canvas 更新
ドラッグ中状態で mousemove イベントが発生した際、現在の座標からX軸方向またはY軸方向に 1px 以上移動した場合のみ更新する。
その部分のソースコードは以下のとおり。
// 画面更新するか判定
// cx, cy ポインタのCanvas座標
// dtest1.DRAG.itemAr[dtest1.drag.item].x ドラッグしているアイテムのx座標
// dtest1.DRAG.itemAr[dtest1.drag.item].y ドラッグしているアイテムのy座標
var updSep = 1; // 何px動いたら画面更新するか
if (Math.abs(cx - dtest1.DRAG.itemAr[dtest1.drag.item].x) >= updSep ||
  Math.abs(cy - dtest1.DRAG.itemAr[dtest1.drag.item].y) >= updSep) {
  // アイテムの座標更新
  dtest1.DRAG.itemAr[dtest1.drag.item].x = cx;
  dtest1.DRAG.itemAr[dtest1.drag.item].y = cy;
  // 画面更新
  dtest1.DRAG.draw();
}
わずか1pxだが、この判定処理を入れたことで移動中のCPU負荷が(自分の環境では)1割ぐらい減った。
1px を 2px にしたら動きがぎこちなくなった。

2) 1/24秒ごとに Canvas 更新
ドラッグ中状態の場合、イベントに関係無く 1/24秒ごとに Canvas を更新する。
ドラッグしているアイテムの座標は mousemove イベントが発生するたびに更新する。
mousedownイベント発生時に、ドラッグ対象アイテムがあったら window.setInterval() でタイマー実行。
mouseup/mouseleaveイベント発生時などに window.clearInterval() でタイマー停止。

1px 移動するごとに更新する場合に比べて、移動中のCPU負荷が(自分の環境では)半分ぐらい減った。
ソースコードの修正箇所は思ったほど多くは無かった。

今後 drag&drop 以外の処理を追加していくつもりだが、
「スタート時にタイマーを実行し、イベント発生時にフラグのオンオフを行う。Canvas を更新するかはフラグをチェックして判定」
とすればCPU負荷を抑えられる上に複雑にならないだろう。

3. その他
・document上の座標をCanvas上の座標へ変換
イベントオブジェクトから取得できるマウスポインタの座標 (evt.pageX, evt.pageY) はdocument上の座標。
CanvasのDOM要素の左上座標は (offset().left, offset().top) で取得できるので、それを使ってCanvas上の座標へ変換できる。
// Canvas描画クラス
  // document上のCanvas左上座標を求める
  // <canvas>タグを認識しないケースを考慮し、同じサイズの<div>タグで囲ってそのDOM要素を取得
  // names.con.id.cvdiv は<div>タグのid
  var $cvdiv = $('#' + names.con.id.cvdiv);
  this.cvpos.x = $cvdiv.offset().left;
  this.cvpos.y = $cvdiv.offset().top;

// mousedownイベント時の処理
  // ポインタ座標をCanvas座標へ変換
  // dtest2.DRAG はCanvas描画クラスのインスタンス
  var cx = evt.pageX - dtest2.DRAG.cvpos.x;
  var cy = evt.pageY - dtest2.DRAG.cvpos.y;

・クリックした場所にドラッグ対象アイテムがあるかの判定
いわゆる当たり判定。
可能なら Canvas をグリッドでエリア分割すれば楽。

久しぶりだと思ったら、この前 HTML5 Canvas のプログラミングしたのは1ヶ月半前だった。
スポンサーサイト



コメント

コメントの投稿

非公開コメント

プロフィール

himax64

Author: 南西
30代後半の無職です。
就活もせずダラダラ生きてます。
作ったもの

最新記事
人気記事
検索フォーム
カテゴリ
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
QRコード
QRコード
カウンター