pirika logo

化学系プログラミング > 比較的新しい化学系プログラミング > HTML5手習 > タッチイベントとかデバイスの回転、ピンチイン/ピンチアウト

2011.9.19

マウスを使ってのお絵かきプログラムはすぐにできました。

コントロールキーなどが押されているときに他の動作に移るプログラムの仕方はこちらの記事にまとめておきました

残る問題は、マウスイベントとタッチイベントを両方使うプログラムの書き方です。
ネットを調べると、マシンのタイプを調べて動作を切り替えるとあるが、それは余り嬉しくありません。

大きな画面用と小さな画面用の2つのプログラムを書かなくてはダメのはしょうがないと思います。

しかし、大きな画面はマウスクリック用、小さな画面はタッチ用としてしまうと、iPadのようなマシンで大きな画面にアクセスした場合に動かなくなります。

どうしても、iPhoneで大きな画面のプログラムにアクセスしたい場合に動かないなどということが起きてしまいます。

小さな画面にマウスでアクセスすということは考える必要はあるのかな? 
それは余り想定はしていないけど、とにかく世の中境界がぼけてきているので共用のプログラムのほうが望ましいと思います。

今までキャンバスに対する描画は次のようにしてマウスが押されたり(mousedown)、動かされたり(mousemove)、ボタンが離されたり(mouseup)する動作を拾って、それに対応するコードを書いてきました。

(function(){
document.addEventListener("DOMContentLoaded",function(){
var canvas =document.querySelector("canvas");
var context =canvas.getContext("2d");

canvas.addEventListener("mousedown",function(event){
event.preventDefault();
var p=get_mouse_position(event);
...
...

}, false);

}, false);

})();

ネットを調べてタッチイベントの取得の仕方を見つけましたが、

document.addEventListener("touchstart", touchDown, false);
document.addEventListener("touchmove", touchMove, false);
document.addEventListener("touchend", touchUp, false);

と書いて、プログラムを走らせると、マウスで使っているときには問題なく動作しますが、iPadを使うとうまくいきません。

iPadの時にはマウスイベントを拾うルーチンを消してしまうとうまく動きます。

どうしてうまくいかないかというと、iPadの場合、タッチイベントも発生するが、同時にmousedownイベントも発生しているようです。
そこで、タッチイベントが発生した後すぐにマウスイベントの処理も行われてしまうため、touchDownしたままtouchMoveが発生したときに線を書くと処理しているのに、touchDownの後、mouseclickも起きてしまうので、そこで処理が途絶えてしまっているようです。

非常に悩みました。タッチイベントが発生しているときには、マウスイベントの処理を禁止しようかとも。

意外な解決でしたが、タッチイベントの頭を、documentからcanvasに変えたらまともに動くようにりました。
イベントリスナーが falseを返していれば、先のイベントに進まないらしいです。

それがdocumentとcanvasで違っていたから両方実行されてしまったらしいです。
(詳しいことは化学者のぼくにはわかりません。信用しないように。とりあえず動くようになったという事は確か。)

開発にはDashCodeを使っているのですが、このDashCodeでは出来上がったHTML5のプログラムを動作形式でセーブするという機能が付いています。

するとHTMLファイルとJavaScriptのプログラム、CSSのファイルがローカルのフォルダーに作成されます。
(デフォルトではサイトというフォルダーの中)そして、付属のiOSシミュレータを立ち上げ、動作チェックするデバイスを選択する。(デフォルトではiPhoneが立ち上がるのでメニューから切り替えます。)

iPhoneの場合はDashCodeから直接走らせられますが、iPadの場合にはこのような初期画面が現れます。ここでSafariブラウザーを選びます。

初めて走らすときには、上のような何も無い画面が立ち上がります。そこで、URLの部分に先ほどセーブしたhtmlファイルをドラッグしてドロップします。

するとプログラムが走ります。

そこに、分子を描いて、計算ボタン(この場合はlogP)を押すとlogPの推算値を計算してくれます。

ピンチイン/ピンチアウト(2本指を使って拡大縮小する)機能はプログラムを全く書かなくても自動的に行われます。
(ただし、後に述べるように問題点もあります。)

シミュレーターを使ってピンチイン/ピンチアウトするには、オプションキーを押します。

すると画面上に2つの灰色の円が現れます。
適当な場所でマウスを押すと、2本指がタッチされたことになります。

そしてマウスを動かすと2つの灰色の円が近づいたり、遠ざかったりします。
そしてマウスを離すと確定されます。

メニューからデバイスの回転を選ぶと、横置きになります。
そしてさらに分子を伸ばしてみます。

プログラマーにとっては非常にありがたいのですけど、拡大/縮小したり、位置を動かしたりしているのに、プログラムになんの変更も加えずに、タッチされた位置から分子を伸ばすことができます。
つまり、プログラムの中では、カンバス上の位置を調べて、そこにある原子から次の原子を書くという操作をしているのですけど、拡大、縮小、移動してもプログラム上の位置は変わっていないという事です。

あたり前のことかもしれないが、すごいと思います。

同じhtmlファイルをブラウザーにドロップすれば、同じように動作します。
ただしピンチイン/ピンチアウトは使えないので、ブラウザーのズーム機能を使います。
縦横置きは知りません。

同じhtmlファイルをiPhoneシミュレータにドロップすると画面は小さいがちゃんと表示され、ちゃんと動きます。

ピンチイン/ピンチアウトすれば、使える範囲内でしょうか?

でも、iPhone用には別に設計したほうがいいと思います。これが専用バージョン。

下のボタンを押すと原子の選択とモードが切り替わります。

GUI以外のプログラムは先程のものをすべて流用しています。

真ん中のiボタンを押すと、計算を始めます。
これがシミュエータの欠点ですが、科学計算自体はシミュレーターを動かしている本体のマックで行うので、この程度の計算は瞬間で終わります。

実機ではどのくらいかかるか? が、わかりません。

非常に簡単に移植できた。と喜んでいたら問題発生。

横置きにしたら、ボタン類が隠れてしまいます。

上にあげようと、指ではね上げようとすると、原子を描いてしまいます。

これはキャンバスに対するイベントを

event.preventDefault();

でブロックしているせいです。

ピンチイン/ピンチアウトはキャンバス以外の場所でしかできません。

ところが全面キャンバスになってしまうとそうした操作ができなくなります。
こうしたプログラムに対しては回転はサポートしないほうが良いかもしれません。
やり方を調べてみようと思います。

そうそう、大事なことを忘れていました。

CANVASの位置です。
タッチイベントは画面全体の位置を拾います。
イベントの収得先をDocumentからCANVASに変えても、CANVASの座標を返してくれるわけではありません。

そこでCANVASの左端を(0,0)に揃えておくとタッチイベントの座標とCANVASの座標は一致します。

2011.5.30

Mac用の外付けトラックパットを買いました。

これを使えば、ピンチイン、ピンチアウトが使えるし、iPad, iPhone用のタッチイベントのプログラムのデバッグもできるかと思いました。

しかし、これはあくまで、ノートブックについているタッチパネルと同じであって、タッチイベントは発生していなかったです。

単なるブルーツース・マウスだと思えば良いようです。

デバッグのたびにHPにプログラムをアップし、実機で動作確認するのはしんどい。
(Macでのシミュレータでは、2本指以上のマルチタッチがシミュレーションできないため)


Copyright pirika.com since 1999-
Mail: yamahiroXpirika.com (Xを@に置き換えてください) メールの件名は[pirika]で始めてください。