unoh.github.com

DOMろうTouchコンテンツ

Mon Sep 27 19:54:11 -0700 2010

Flashエンジニアnao ozawaです。最近あんまりゴリゴリとFlashでコーディングしていません。なんでかなぁ!まるで働いていないみたいじゃないですか。一応ちゃんと仕事してるんですよ?
まぁ、そんな感じの毎日なので、実はここ数日、作業のかたわら、スマートフォン向けページのレイアウト方法を色々考えております。

・ブラウザの画面回転するのめんどくさくね?

 みなさんご存知のように、iPhoneを筆頭に最近のスマートフォンは、携帯を横に向けると、合わせてくるりと画面が横レイアウトに変わります。()く言う私も初めてソレに遭遇したときには驚きを隠せず、暫くは日がな一日iPhoneをくりくりと縦にしたり横にしたりして過ごしていたものです。それはそれは楽しかった。
が、しかし、最近スマートフォン向けのページを作る側にまわってみて、はじめて気がついたのです。

画面の幅が変わるのって、めんどくせぇ

もう喜んでる場合じゃない。あり得ないほどめんどくさかったのです。

 そう思ったきっかけはクリッカブルマップ。懐かしい響きですね。Flashが全盛を極めてからは、みんなすっかり利用されなくなってきていますが、残念ながらiPhoneではFlashは動きません。そのため、どうしてもクリッカブルマップを使いたかったんですが、ここで問題になったのが、画面の回転なのです。
 クリッカブルマップは画像上の絶対座標によってクリックエリアを決定しています。手持ちのiPhone4では画面が回転した時も横幅の拡大は「表示」の拡大という扱いになっているため座標はズレないのですが、実はXPERIA(Android1.6)では、横表示になった時に画面の再描画が行われるため、画像が縮小されます。
 じゃぁ、初めから画像の表示サイズをピクセルで指定しておくとか、機種ごとにテンプレートを用意すればいいんじゃない?という意見もあろうかと思います。自分でもそう思います。ですが、それも面倒じゃnそこは、エンジニアの端くれとして、スマートにコードを書いて解決したいと決意した次第なのです。
 そこでDOMの登場です。前置きが長くなりましたが、やっと本題です。

Q. DOMってなによ?
A. Document Object Modelの略で、簡単にいえばJavaScriptからHTMLタグとかCSSのパラメータとかを書き換えられるHTML5時代のスタンダード・ウェポン。iPhoneでも使えるよ!ジオン公国のツィマッド社が開発した陸戦用モビルスーツとは親戚関係。

・座標は比率から求めよう

 画面サイズも違えば縦と横での変化もあるページを、ひとつのコードで処理する。手っ取り早くコレを実現するには、画面幅に対して画像は80%のサイズ、というように、画面の横幅に対する比率を基準にしてしまえばOKです。
残りの数値は、全て画面が描画される都度に計算しましょう。なお、タグの属性の指定には「setAttribute」を使います。

[イメージタグ]
<img src="img/map.gif" border="1" usemap="#map_test" name="map_test" id="map_img" />
*サイズの指定はしない

[JavaScript]
// mapという新しいオブジェクトにID名「map_img」(imgタグで設定したID)を割り当て
var map = document.getElementById("map_img");
// mapというオブジェクトのwidth(横幅)にwindow.innerWidth(画面の横幅)の80%(* 0.8)を指定
map.setAttribute("width",window.innerWidth * 0.8);
これで、画像の横サイズは、画面の横幅が100ピクセルの時は80ピクセルに。640ピクセルなら512ピクセルになるわけです。

で、あとはクリッカブルマップの<area>タグで、クリックエリアを指定するcoords属性の座標を地味に計算。
例えば100x100pxの画像の(x=20,y=10)の場所に座標がある場合は、(x=100*0.2,y=100*0.1)と表せます。
キモは画像のサイズを1としてゼロ座標からポイントまでの長さを小数点で表すこと。この例では、aポイントは画像の横幅に対して1:0.2の位置、縦幅に対して1:0.1の位置となるという事ですね。
var ax = document.images["map_test"].width * 0.2;
var ay = document.images["map_test"].height * 0.1;
こんな感じ。見たまんまですね。比率は、Photoshop等で頑張って測りましょう。

こうしてax,ay〜dx,dyまで4点の座標を求めたら、createAttributeでタグに直接記述されていない(予め書かないでおいた)coords属性を作成し、適用します。
var map_area = document.getElementById("AreaID");
var set_coords = document.createAttribute("coords");
set_coords.nodeValue = ax + "," + ay + "," + bx + "," + by + "," + cx + "," + cy + "," + dx + "," + dy;
map_area.setAttributeNode(set_coords);
これで座標の指定は完璧。 座標指定のスクリプトをhoge()など好きな名前の関数にして、

window.onload = function(){
	hoge();
}
とすれば、ページを読み込んだ時に実行され、無事クリッカブルマップが動くようになります。

・回転した場合の処理

iPhoneには「onorientationchange」という魔法の呪文でブラウザの回転イベントを取れるのですが、Androidでは未対応なので、ここは素直に「onresize」(画面サイズが変化した場合のイベント)を使います。


window.onresize = function(){
	hoge();
}
これでOK。 本当は「回転しないように」出来れば素晴らしいのですが、今のところ、そんな神コードは思いつかない(無くはないけど面倒)ので、まぁ今日のところは、このへんで勘弁してやろう。iPhoneめ参ったか。フヒッ。

13:49 追記
書きなぐった記事を読みながら揚げパン食ってたら思いついた。回転しない(ように見える)のは、結構簡単にできるかも?上手くできたら後日投稿します。

・まとめ

今回はクリッカブルマップでしたが、この考え方で、ブラウザの横幅が変化してもレイアウトを維持できるコンテンツが作成可能です。
使い方は色々あるので、ぜひ皆さんもDOMってみてください。

つーかiPhoneでFlash動くようになんないかなぁ!ジョブス爆発しろ!
この秋出ると噂の新型MacBookAirも、きっとまた買っちゃうんだからね!

では、また。