jQuery Mobile 1.1でPublickeyのモバイル版を作ってみた
Publickeyのコンテンツをモバイル向けに最適化した「Publickey Smart Edition」をバージョンアップしました。今回はjQuery Mobile 1.1を使い、モバイル対応の機能を以前よりも活用したものになりました。
jQuery Mobile自身、以前のバージョンより動きがスムーズになったことに加え、今回からjQuery Mobileの標準機能をそのまま使うことでページのロード時間も短くなりました。
画面遷移ではアニメーションを使い、画面をスワイプすると前記事、次記事へ移動するようにしたので、よりモバイルらしいWebアプリケーションになったと思います。
画面サイズや機種などに依存しないように作ったつもりなので、iPhone/iPod touch/Android/Windows Phoneなど主要なスマートフォンで参照できるはずです(手許にあるiPod Touch/iOS 5.1とDigno/Android 2.3でチェックしました。Windows Phoneは未確認)。もしも画面が乱れたりした場合には、そっとリロードボタンを押してやってください。
Publickey Smart Editionは無料で登録なども不要でご覧いただけます(PCからも前述のリンクからアクセスできます。でもPCからの人は普段は通常版で広告も一緒に見てくださいorz)。時期は未定ながらいずれ有償サービスにしたいと考えていますが、少なくともこの先3カ月は無料でご覧いただけますので、お気軽にお試しください。
さて、もともとPC用のWebブラウザ向けに作ったPubilckeyをどうやってモバイル対応したのか、いくつかポイントを紹介したいと思います。
画面レイアウトをモバイル対応にする
PC用のWebブラウザ向けに作ったPublickeyのオリジナル画面をモバイルデバイスの小さな画面に合わせるには、タイトルと本文のみに削ぎとした新しいレイアウトにしなければなりません。と同時に、モバイル向けのアイコンなど新たなユーザーインターフェイスの要素が必要です。
PublickeyではCMSにMovable Typeを使っています。これとjQuery Mobileを組み合わせて、簡単にモバイル向けレイアウトが実現できます。例えば、記事ページはヘッダ部分と本文からなっていますが、コードを簡単に書くと次のようになります。
<div data-role="header" data-theme="b">
<a href="/index.html" data-role="button" data-icon="home"
data-transition="fade">Home</a>
<h1>Publickey Smart Editionβ2</h1>
</div>
上記のコードでは、data-role="header"でヘッダ表示にして、そこにホームボタンをdata-icon="home"で付けています。続いて記事タイトルと本文。
<div class="maincol" data-role="content" data-theme="d">
<h1><$MTEntryTitle$></h1> <!-- これがタイトル -->
<$MTEntryBody$> <!-- これが本文 -->
</div><!-- end of maincol -->
実際には、タイトルの下に日付を入れたり、記事下に前ページと次ページのナビゲーションを入れたりしていますのでもう少し複雑なコードになっていますが、基本的にはこれだけです。
MovableTypeのテンプレートは、PC用とモバイル用の2種類を用意し、1つの記事に対してURLが異なる2種類のHTMLを生成しています。
jQuery Mobile用HTMLの注意点
ご覧のように、jQuery Mobileに対応したHTMLを記述するのは難しくありませんが、HTMLを記述する際に気をつけなければいけないポイントが2つあります。1つは、基本的にはidを使わずclassを使うこと、もう1つは全ページの<head>~</head>の内容を同じにすることです。
その理由は、jQuery Mobileではページ遷移の方法が特殊になるためです。
通常、「ページA」内にある「ページB」へのリンクをクリックすると、「ページB」がロードされて「ページA」は消えます。ところがjQuery Mobileでは異なる動作をします。
jQuery Mobileを利用したWebサイトでは、「ページA」内にある「ページB」へのリンクをクリックすると、「ページA」に「ページB」の<body>~</body>が読み込まれて画面に表示されるのです。
これにより「ページB」の表示時に「ページB」の<head>~</head>にあるCSSやJavaScriptなどは無視され、ページAのCSSやJavaScritpが引き続き有効になっています。「ページB」のロード時にいちいちCSSやJavaScriptを読み込むことはないので高速にページの読み込みが行われますが、一方ですべての記事で<head>の内容を同じにしておかないと、CSSやJavaScriptが正しく働かなくなってしまいます。
idを使うべきではない、というのも同じ理由です。ページAとページBが1つのDOMツリー内に共存する可能性があり、さらにリンクをクリックすればページC、ページDとどんどん読み込まれていく可能性があります(適切なメモリ利用量になるよう、jQuery Mobileでは自動的な解放もしてくれるらしいのですが、それはまた別の話)。そのため、すべてのページに対してユニークなidを保証できない限り、idの代わりにclassを使うべきでしょう。
Publickeyもモバイル用のHTMLではidをclassに書き換え、それにあわせてスタイルシートも書き直しました。
画面遷移アニメーション
画面遷移するときにアニメーション効果があるのはモバイルアプリケーションでは一般的です。jQuery Mobileを使うと、リンクに以下の属性を記述するだけで簡単にアニメーション効果を組み込むことができます。Publickey Smart Editionで使ったのは、以下の2種類。
data-transition="fade"
これはリンク元の画面がフェードアウトし、リンク先がフェードインしてきます。
data-transition="slide"
リンク元の画面が左へスライドして消え、リンク先の画面が右から表れます。次の記事を読むときに使っています。data-direction="reverse"を追加すると逆方向になるため、前の記事を読むときにはこの属性を追加しています。
画像を画面にあわせて縮小する
モバイル画面に合わせた記事を表示するときの、大きな課題の1つが画像のサイズです。もともとPublickeyではPC用の画面にあわせて画像のサイズを最大で横500pxにしています。しかしモバイルデバイスの画面サイズでは500pxの画像ははみ出してしまうため、モバイル向けに画像を縮小しなければなりません。
しかも縮小すべきサイズは1つではありません。iPhoneやAndroidなど機種ごとに画面の幅は違いますし、同じデバイスでも縦方向(ポートレイト)と横方向に傾けたとき(ランドスケープ)でも横幅が変わります。
そこでPublickey Smart Editionでは、画面縮小をJavaScriptを用いて動的に実現することにしました。といっても、わずか8行のコードで記述できる簡単なものです。
以下のコードでは、まず画面の幅を取得します(34を引いているのは左右のマージン)。そして、画像やdiv、iframeなどがそれより大きければ画面にあわせて縮小する、というコードです(実際のコードより簡素化しています)。これを画面が表示されたタイミングで呼び出しています。
var maxWidth = $(window).width() - 34;
$('img,div,iframe').each(function(){
var w = $(this).outerWidth();
if (w > maxWidth) {
$(this).width(maxWidth)
.css("padding-left","0").css("padding-right","0");
}
});
この方法の利点はサーバに負担がかからず、さまざまな横幅のデバイスに対して柔軟かつ容易に対応できる点です。一方で、弱点はサーバで縮小するよりも動作が不安定で、特に通信が不安定な環境では画像縮小されないまま表示されることがあります(また、実際の実装ではポートレイトからランドスケープに画面を傾けたとき、拡大するようにも作ってあります。やや動作が不安定ですが……)。
ただ、jQuery Mobileでは前述のように最初に読み込まれたJavaScriptは以後ずっと再読込されず作動状態が続くため、ページごとにJavaScriptが読み込まれて実行されるよりも動作は安定するはずです。そのため、JavaScriptでの画面縮小はjQuery Mobileに向いた実装ではないかと思っています。
また、記事中に表れる関連記事のリンクも、これと同じ手法で動的にモバイル用のURLに書き換えています。ですので、関連記事などをクリックした場合でもPC用のページではなくモバイル用のページに移動します。
スワイプに対応する
タッチインターフェイスを備えたモバイルデバイスでは、画面を横にさっとなでるスワイプの動作で次の画面へ移動するというのは一般的な動作です。そこで、Publickey Smart Editionでも実装してみました。jQuery Mobileにはスワイプ動作をイベントとして認識する「swipeleft」と「swiperight」が用意されているので、それを画面にバインドするだけです(実際の実装はチェーンにしてます)。
$(".maincol").unbind();
$(".maincol").bind("swipeleft", gonextentry );
$(".maincol").bind("swiperight", gopreventry );
イベントが発火したら、次の記事、もしくは前の記事へ移動する関数を呼び出しています。
次の記事、前の記事に移動するには、現在の記事に記述されている前記事、次記事へのリンクをスワイプのイベントの直後に$(#id)で読み込んで移動しています。
HTMLに埋め込んであるidはその記事のURLをベースにしたユニークな値です。そのidをJavaScriptでも生成するためにjQuery Mobileの変数を参照して現在のURLを取得しているのですが、jQuery MobileではURLがハッシュベースで、iOSとAndroidで得られる値も違っていたため、それを元にユニークなidを生成するのにハックっぽいテクニックを編み出す必要がありました(もしかしたら別の機種やOSではさらに挙動が異なるかもしれません……)。
おおよそ2日程度で実装
ざっと説明してきたように、jQuery Mobileを使えばスマートフォン対応にするのにそれほど工数はかかりません。今回も正味2日程度の工数でした(書いたコードは100行前後でした)。MovableTypeやWordpressなどCMSのテンプレートとJavaScript/jQueryに慣れていればそれほど難しくないはずです。
一方で手間がかかるのが動作確認です。スマートフォンにはFirebugのような便利なツールもデバッガもなく、画面が小さいため操作も面倒ですし、複数のデバイスでのチェックも必要です。今回もデバッグのためにずいぶんalert()を埋め込んでチェックしました。
ここがもっと効率化すること、そしてjQuery Mobileを使っていてもなおAndroidとiOSの動作に細かな違いがあったので、こうした部分の完成度があがっていけばモバイルの開発効率はもっとあがることでしょう。
あわせて読みたい
グーグル、BigQueryを正式公開。SQLで大規模データに対して高速処理
≪前の記事
2012年4月の人気記事「Meteorはすごい」「OracleがGoogleを訴えた理由」「jQuery Mobile 1.1登場」