enchant.js touchmoveで画面外にドラッグすると発生する不具合解消

アカズノハコ 制作後、明らかになった標記のバグ解消方法を書きます。enchant.jsにてtouchmoveイベントを使う際には気を付けないと、使いにくいUIになってしまう点があるので注意したほうがよいです。

バグ状況は標記のとおりなのですが、これだけみてもどんな問題化いまいちわからないと思うので、どういった問題かを説明します。

 

enchant.js touchmoveの落とし穴!

ここに、touchmoveを使ったサンプルがあるので、これで問題点を説明します。

Playボタンを押すとプログラム開始です。くまをクリックしてからドラッグすると、くまがついてきます。ドラッグ時にイベントリスナー内の関数を実行する仕組みですね。

上にあるjavascriptのタブをクリックするとコードが見られます。コードの説明みたらなんとなく動作がわかると思います。

で、ここから問題状況を再現します。クマをドラッグしたまま、画面外に引っ張ってクリックをやめてください。その状況で画面内にマウスを移動させるとどうなるでしょうか。

 

クリックしてないのに、画面内のマウスにクマが追従してきます。

つまり、ドラッグしてないのにtouchmoveイベントハンドラが実行されてしまうのです!

これ、アカズノハコのようなドラッグでピースを動かす挙動だと、ユーザーにストレスを与える原因になってしまいます。ドラッグ時に画面外にマウスを持って行ってしまうことは結構多いからです。

で、実際に苦情がコメント欄に来たので、以下の解決策を提案します。

画面外出そうになったら、touchmoveイベント削除する

解決したプログラムが以下となります。画面外でドラッグをやめても、戻ってきたときには追従しないことがわかると思います。

解決策として、画面外に出そうになったら、touchmoveイベントリスナーを削除します。逆に、touchstart時にはtouchmoveイベントリスナーを追加します。

画面外に出る前にtouchmoveを削除してしまえば、問題ないやろという解決方法です。

//touchmoveイベントで追加する関数
function Move(e) {
text.text=Math.floor(e.x)+","+Math.floor(e.y);
//画面外に出そうなら、touchmoveイベントを削除する。
  if(e.x<10||e.x>310||e.y<10||e.y>310){ //この範囲を超えたら画面外ギリギリの位置なのでtouchmoveイベントを削除
    this.removeEventListener("touchmove", Move);
    return;
  }

  // タッチした位置に移動
  var x = e.x - (sprite.width/2); // スプライト幅の半分の値を引くことで中央にする
  var y = e.y - (sprite.height/2); // スプライト高さの半分の値を引くことで中央にする
  sprite.moveTo(x, y);
}
//クリック時にtouchmoveイベントを追加する。
scene.addEventListener("touchstart",function(e){ 
  //関数を使ってシーンにtouchmove関数を追加
  this.addEventListener("touchmove",Move);
});

 

今回は画面端から10pxをとってますが、結構余裕とっているので、適宜調整してください。(touchmove範囲がその分狭まってしまうからです。)

 

以上です。ご査収ください。