前回は、座標計算の説明をしました。座標をドラッグすると、JavaScriptで結果が見れるようにしました。
せっかくJavaScriptでマウスのドラッグを受け付けているのですから、これがそのまま動画にできたら便利ですね。今回はこれに挑戦してみましょう。
JavaScript座標回転プログラムの動作
まず、前回のvector.htmlを見てみましょう。divタグで作られたテキストは、スタイルがposition:absolute;になっています。ですから、スタイルのleftとtopに値を指定することで、任意の位置に動かすことができます。昔はこういうのをスプライトと呼んでいた時代もありました。
setuphandle関数では、このdivタグにイベントハンドラを登録しています。手間を省くため、クロージャとコールオブジェクトを用いて、setuphandleに渡されたobjをonmousedownの中で使っています。onmousedownのときのマウスの座標をoffsetXとoffsetYという形で保存し、これもonmousemoveの中で使っています。ちなみにparseIntは、スタイルにつく「px」を取り除いて数値にするのに利用しています。
ドラッグされたときは、setupvector関数を呼んで、すべての矢印を計算しなおしています。矢印はオブジェクトを使っており、calcメソッドの中に、矢印ごとの個別の計算処理をあとから登録してあります(JavaScriptでは、new 関数名()とすると、オブジェクトが作られてから関数名()がコンストラクタとして呼ばれます)。矢印のものは多角形(SVGのpolygon)で描いています。矢印の矢の座標は、前回解説した座標計算で求めています。
マウス操作をPHPサーバで記録するには
さて、これを動画にしようとするわけですが、JavaScriptでは画像が作れません。そこで、座標をサーバのPHPに渡して、サーバ側で画像を作ることにします。これには、いくつかのやり方があります。1つ1つ見ていきましょう。
1つ目の方法は、ドラッグ操作と平行してサーバにリクエストを出し、リアルタイムに動画を作る方法です。今をときめくAjaxというやつです。ですが、これはとても処理がややこしくなります。個人的には、他の方法がないかを調べておきたいところです。
2つ目の方法は、ドラッグ中の情報をフォームに書き出しておき、あとでまとめて送信する方法です。リアルタイムにはなりませんが、フォームをチェックすればデバッグも簡単ですし、wikiなどに出力するような拡張もできます。
もう1つのポイントは、サーバ側に渡すデータの抽象度です。矢印の始点と終点の座標を記録するのが一案です。この方法だと、PHP側ではJavaScript側と同じやり方で矢印の矢の座標を計算する必要があります。つまり、同じことをするコードを、PHP版とJavaScript版の2つ用意して保守しなければならないということです。類似の案として、オブジェクトをシリアライズして渡すという方法があります。
別のやり方としては、計算済みの多角形(polygon)の座標をPHP側に渡す方法もあります。JavaScript側では矢印の始点と終点から矢の座標を計算し、多角形のSVGにしていますが、PHP側はこれをimagefilledpolygonなどに渡すことになります。コードの重複がないので、JavaScript側のコードで矢の形を変えれば、PHP側にも自動的に反映されることになります。ただし、この多角形が矢印であるといった情報は失われてしまいますので、PHP側で特定の矢印だけ形を変えたい、といった対応はできなくなります。
これは喩えていうと印刷のときに文字データを渡すか、ビットマップにしたデータを渡すかのような違いです。文字データを渡す場合、両方に同じフォントが必要になります。ビットマップの場合、追加の加工をしたい場合などに制限が出てきます。
どちらも一長一短あるのですが、今回はデータの送信はフォームを使ってまとめておこなうようにし、送るデータは多角形の座標としました。理由ですが、少なくとも最初のうちはできるだけシンプルにしたく、またコードの重複も避けたいと考えたからです。具体的なやり方ですが、フォームを使ってテキストエリアを送信します。テキストエリアの内容は、時刻、多角形、テキストが1行ごとに並んでいます。PHP側ではこれを読み、画像を生成します。
まず、これがうまく動くかを見てみましょう。送信ボタンを作り、これを押したときにそのときの座標データを生成して送信します(formのonsubmitを使っています)。PHP側ではここから画像を作り、ブラウザに返します。
うまくいったら、次はドラッグの都度テキストエリアに出力するようにしてみましょう。テキストエリアにはドラッグが完了するたびに座標データが追記されていきますので、デバッグはしやすいと思います。PHP側は複数の画像を生成することになりますから、画像はファイルに出力し、IMGタグを並べたHTMLをブラウザに返すようにしました。実はこのPHPは、前回の画面キャプチャで使ったものです。
なお、送信したあとに、別の操作をして再び送信すると、前回生成したファイルは上書きされてしまいます。サーバサイドではありますが、これは同時に1人しか使えませんので、webで公開するには向きません。サーバ側に画像ファイルを作る手段と考えるとよいと思います。
最後に、ドラッグの経過をリアルタイムに出力するバージョンです。onmousemoveのたびにテキストエリアを書き換えると遅くなりますので、文字列は変数に保持しておき、送信時にテキストエリアに入れるようにしました。PHP側は、時刻データを見て同じ画像をいくつも出力し、マウス操作を再現するようにしています。
今回はマウスカーソルは表示しませんでしたが、簡単に表示できるはずです。たとえばボタン操作をわかりやすく表示するなど、いろいろな応用が考えられます。ぜひ、うまく利用してみてください。