どうも!LSSです!!
昨日の記事、
スマホでは動作しませんでしたが、今後これを使ってブラウザゲームとか作る上ではやはり、スマホでも遊べるようにしたい!!
というところで、スマホ対応を試みてみました!
マウスドラッグかスマホスワイプで移動する「もぐら」
コード
<div id="g1" style="position: relative;" draggable="true">
ドラッグorスワイプで移動させたいものをここに書きます
</div>
<script>// <![CDATA[
g1.addEventListener('dragend',dgend,false);
g1.addEventListener('touchstart',tcstart,false);
g1.addEventListener('touchend',tcend,false);
function dgend(e){
g1.style.position='absolute';
g1.style.top=(e.pageY-50).toString()+'px';
g1.style.left=(e.pageX-50).toString()+'px';
}
function tcstart(e){
e.preventDefault();
}
function tcend(e){
e.preventDefault();
g1.style.position='absolute';
g1.style.top=(e.changedTouches[0].pageY-50).toString()+'px';
g1.style.left=(e.changedTouches[0].pageX-50).toString()+'px';
}
// ]]></script>
赤文字部分が、今回追加したコードになります。
思ったより手間取りました^^;
いやぁ…そもそもコードはPCで「HTML編集」画面で書いているのですが、動作確認はAndroidタブレットで行っています。
そのため、「下書きを更新する」を押しては、タブレットで開き直して確認…というのをマトモに動作するようになるまで延々と繰り返しましたw
それでも作り始めるまでは
「dragendイベントと同様にtouchendイベントで同じ関数(dgend)を呼び出すだけで実現するかな?」
という甘~い考えを持っていましたが、とんでもなかったですw
難関その1 スマホにはマルチタッチがある事
マウス操作の場合、マウスカーソルはひとつしかないので、「マウスを移動し終えた座標」も当然ひとつだけ。
なので、「e.pageX」「e.pageY」で気軽に取り出せるのですが…スマホには「マルチタッチ」という概念があります。
複数の指を画面に同時につけて行う操作で、身近な例でいうと、拡大・縮小を行う「ピンチイン」「ピンチアウト」操作がありますね。
あれをプログラムの側から「どこに指が触れたか」を認識するには、複数ある座標の全てを認識できないといけない、って事になります。
…とは言え、マルチタッチを活用したアプリもそれほど多くないので、
すっかり忘れていましたwww
この「もぐらの移動」についても、複数指の操作は不要なので、結局のところ、
g1.style.top=(e.changedTouches[0].pageY-50).toString()+'px';
g1.style.left=(e.changedTouches[0].pageX-50).toString()+'px';
↑この書き方で座標を取り出せます(1本指操作であれば)、という結論に行きつきました。
※ [0]という書き方は配列と同じ扱いで、もうひとつ座標があればe.changedTouches[1]で取り出せる、って事になります。
難関その2 スワイプ操作は画面スクロールになる
これで、もぐらを動かせるようになりました。
が、「上下に動かそうとすると画面がスクロールしてしまい、結局もぐらを動かせない」という第二トラップが発動してしまいました^^;
…そもそも、イベント監視する時に指定している、
g1.addEventListener('touchend',tcend,false);
最後のfalseが「その操作本来の作用をキャンセルする」という意味のはずでしたが、これだけではスワイプ操作でスクロールになるのをキャンセルできないようです。
※…というわけでもないようなので、打消し線
じゃあどうするんだ??と調べてみると、
e.preventDefault();
というのを一行書いておくと、それで「その操作本来の作用をキャンセルする」事ができるそうです。
(ちなみに今更ですが、 e は任意のイベント変数です。関数定義時にfunction tcend(e){で決めた名前になります)
だもんで、touchend時に発動する関数「tcend(これも任意の名前です)」内に書きました…が、それでもやはり画面スクロールしてしまいます^^;
考えてみれば、touchendが発動するのは「スワイプ操作が終了した時」であって、「画面スクロール」はスワイプ操作が完了しなくても指を動かしてる間、それについてくるんですね。
なので、さらにもうひと手間ですが、
g1.addEventListener('touchstart',tcstart,false);
で「タッチ操作開始」も別途イベント監視して、そこで呼び出した関数内で、
function tcstart(e){
e.preventDefault();
}
と記述する事によって、
「この操作(もぐらに指を乗せてから始まるタッチ操作)は、画面スクロールしなくていいです」
とキャンセルをかけています。
…これでようやく、スマホでも もぐらを動かせるようになりました^^(確認したのはタブレットですが)
あとがき
同じような(しかも、一応遊べるとはいえ大半がよく分からない内容)記事を続けてしまいました^^;
残る不安は…「iPhoneでも動くか?」ってとこですねw
ってなとこで、今回はこのへんで!
次回もまた、よろしくお願いします^^