2011年9月13日火曜日

第3回HTML5のススメ

もうすぐ、ゲームショウの季節になりました。たのしみですね。KOYAです。

さて、今回は、「ネイティブにも負けない!HTML5のタッチイベント」について
話していこうと思います。

で、どうすればタッチイベントが拾えるの?って感じですが、以下の数ステップで
簡単に実現することが可能です。

以下、このような指定。
 
canvas.addEventListener("touchstart", ?????, false);
canvas.addEventListener("touchmove", ?????, false);
canvas.addEventListener("touchend", ?????, false);
canvas.addEventListener("touchcancel", ?????, false);

とまぁタッチに関するイベントが4つあるので、canvasで使用するなら、Eventに登録するだけで使えちゃいます。

※addEventLisstenerの仕様に関しては割愛させて頂きます。

で具体的にどんなイベントの際に発生するのか?ってことですが・・・

touchstart・・・タッチ入力開始時に発生。
touchmove・・・タッチスライド時発生。
touchend・・・タッチイベント終了時発生。
touchcancel・・・今のところ不明。わかる方がいらっしゃいましたら、たゆたうへご連絡ください。


とこんな感じです。

さぁこれでとりあえずタッチイベントは拾えました。
今回もサンプルで何か作りましょう。

ってことで、第1回から引き続き使用している、たゆたうロゴをタッチしてドロップ&ドラッグで
動かしちゃうスクリプトを作ることにします。

さっそく以下ソース。

 
// キャンバス
var canvas;
// コンテキスト
var ctx;
// キャンバス幅
var canvasWidth;
// キャンバス高さ
var canvasHeight;

// 指定オブジェクト
var obj;
// 画像オブジェクト
var img;
// タッチオブジェクト
var touch;

window.onload = function() {
 init();
};

/**
* 初期化処理
*/
function init(){

 // キャンバスの取得を行う。
 canvas = document.getElementById('testCanvas');
 // コンテキストの設定。
 ctx = canvas.getContext('2d');

 // キャンバスの塗りつぶし。
 canvasWidth = 400;
 canvasHeight = 600;

 // イベントの挿入
 canvas.addEventListener("touchstart", startListner, false);
 canvas.addEventListener("touchmove", moveListner, false);
 canvas.addEventListener("touchend", endListner, false);
 canvas.addEventListener("touchcancel", endListner, false);

 // オブジェクトクラスを生成する。
 obj = new Object();
 obj.x = 100;
 obj.y = 100;

 // ドラッグ時のオブジェクト
 touch = new Object();
 touch.x = 0;
 touch.y = 0;
 touch.dropFlag = false;
 touch.startX = 0;
 touch.startY = 0;

 // たゆたうロゴ
 img = new Image();
 img.src = "http://?????????????????/tayutau.png";

 // ロード終了時に描画等開始。
 img.onload  = function() {
  obj.w = img.width;
  obj.h = img.height;
  // 描画処理を行う。

  setInterval("loop()", 50);
 }
}

/**
* ループ処理処理
*/
function loop() {

 // ドロップされていない場合、初期化。
 if (false == touch.dropFlag) {
  obj.x += touch.x;
  obj.y += touch.y;
  touch.x = 0;
  touch.y = 0;

 }

 // 背面を黒塗り
 ctx.fillRect(0, 0, canvasWidth, canvasHeight);
 // 描画
 ctx.drawImage(img, obj.x + touch.x, obj.y + touch.y);
}

/**
* タッチイベント開始
*/
function startListner(event) {

 // キャンバスの絶対座標を取得する。
 var rect = event.target.getBoundingClientRect();

 // キャンバスでのタッチ座標を取得する。
 touch.startX = event.touches[0].pageX - rect.left;
 touch.startY = event.touches[0].pageY - rect.top;
 event.preventDefault() ;

 // 画像に当たっていた場合
 if (touch.startX > obj.x && touch.startX < obj.x + obj.w) {
  if (touch.startY > obj.y && touch.startY < obj.y + obj.h) {
   touch.dropFlag = true;
  }
 }
}

/**
* 移動
*/
function moveListner(event) {

 // つかんでいない場合
 if (false == touch.dropFlag) {
  return;

 }

 // キャンバスの絶対座標を取得する。
 var rect = event.target.getBoundingClientRect();
 // 現在のキャンバス位置から-開始位置の座標の算出

 touch.x = (event.touches[0].pageX - rect.left) - touch.startX;
 touch.y = (event.touches[0].pageY - rect.top) - touch.startY;
}

/**
* 終了イベント
*/
function endListner(event) {
 touch.dropFlag = false;

}

って事で、完成しました。少々長かった。
もっと簡単に実装できそうですが、サンプルソースって事で勘弁して下さい。

一部気になるコードだけ説明します。

1つ目は、

event.touches[0].pageX

なぜか配列になってる。。。
そう、マルチタッチだって対応してるんです。
なので、うまいことやれば結構なリッチでハッピーなゲームが作れるかもしれません。


そして2つ目は、

 event.preventDefault() ;

資料などを読むと、

イベントがキャンセル可能な場合、preventDefault メソッドを使用するとイベントのキャンセルを通知できるため、そのイベントの結果として通常は実装により実行されるデフォルトのアクションが実行されません~


と書いてあります。
何のために必要なのか?

最初はこれを記述せずに実装していたのですが、
タッチして移動するたびにブラウザがスクロールしてしまい、
うまく動作しなかったわけです。

こいつを入れてあげると、タッチイベント以降のイベントがキャンセルされるため、
スクロールせずにうまくタッチイベントが動くのです。

タッチイベントなんか簡単だろう。と思い実装してみたは良いものの
まさかこのような所でハマるとは思いませんでした。

以上、完。


0 件のコメント:

コメントを投稿