JavaScriptで画像のオフラインキャッシュを実装する

もうすぐクリスマスシーズンなんですかね?本間です。

巷で話題のイケメンホイホイ(以下イケホイ)ですが、このたびiPhone用サイトがオープンしました。 それにあわせて新機能も搭載!イケメン写真にタグを付ける機能と、iPhoneでぼんやり眺めているだけで楽しいビューア機能です。 タグ機能はPC版にも搭載されましたので、ぜひぜひみんなで色んなイケメンにタグを付け合ってくださいね。 タグが付くことで、オススメの精度が上がりますよ!

ビューア機能は、自分がゲットしたイケメンズがiPhone上で次から次へと表示される機能です。 オフラインでも表示できる機能付き! 電車の中で見るも良し、卓上に置いて眺めるも良しです。

イケメンホイホイビューア利用シーン

あなた好みのイケメンがゾロゾロ。イケメンホイホイのサイトはこちら!

イケメンホイホイ

…うーん、ユーザ層がかぶらなそうだな、この記事。

さてさて、本題はHTML5の機能を使った画像のオフライン表示についてです。

イケホイiPhoneでは、HTML5の機能を色々実験しています。単独ブラウザの強み、ですかね。

一般的にHTML5で画像をオフライン表示可能にするのは難しくありません。 Offline Application Cachingの機構を使えば、manifestファイルに当該画像のパスを記述しておくだけで簡単にキャッシュできます。 manifestファイルでは、manifestファイルが読み込まれた時点で、サーバにアクセスしてキャッシュ対象のファイルを保存します。 なのでワイルドカードとか、このディレクトリ以下を全部キャッシュ、とかはできないワケですね。

今イケホイには15000枚近いイケメン画像があります。 個別のユーザごとに表示する画像は違うので、それぞれ何らかの方法でキャッシュする必要があります。 ここで考えられるのは、manifestファイルを動的に作成するか、manifestに頼らない方法でキャッシュを実装するか、ですね。

今回は後者の、manifestファイルに頼らずにキャッシュを実装してみました。 使う技術はこれもHTML5のlocalStorageです。 ローカルに恒久的にテキストデータを保存しておけるというシロモノですね。 任意の名前のキーごとに値を保存するだけの機能なので、扱いが簡単です。 このlocalStorageに画像データを保存します。

その前に画像の表示の仕方を考えましょう。 ビューア部分は今回、これまたHTML5のCANVAS要素を使って描画しています。 CANVASに画像を貼りつけるには、キャンバスコンテキストのdrawImage関数を使います。 このdrawImage関数のコピー元には他のCANVAS要素か、Imageオブジェクトを利用できます。 ここではImageオブジェクトを使います。

空のImageオブジェクトはnew Imageで作ることができます。 この後、通常ならば画像のURLをsrcプロパティに指定するところですが、ここにはBase64エンコードした画像データをdataスキームを使って渡すことができます。 dataスキームに関してはRFC 2397 - The "data" URL schemeでもどうぞ。

つまりBase64でエンコードした画像データを用意すれば、表示上もlocalStorage上も問題なく使えることになりますね。 というわけで、サーバには画像をdataスキームに変換して送信するAPIを用意しました。 ブラウザがオンラインの場合、このAPIに対してXHRでデータをリクエストします。 受け取ったデータはimage.srcに渡すと同時にlocalStorageにも保存しておけばOK。 次回はlocalStorageにデータがあれば、そちらから読みだすようにすればオフライン画像キャッシュの出来上がりです。

ちなみに余談ですが、CANVASは画像からこのdataスキームを取り出すtoDataURLという関数を持っています。 ローカル側ですでに展開済みの画像をJPEGやPNGにエンコードして文字列にしてくれる機能ってことですね。 つまりサーバ側に上記のAPIを用意しなくても、クライアントに画像を読み込めばdataスキームを作りだすことができます。 2回エンコードを通すことになってしまうので、JPEGだと画質の劣化が防げないため、今回は使用しませんでした。 PNG受け取りPNG保存ならいいかもしれませんね。

カヤックではイケメンをローカルストレージにホイホイしたい女性プログラマを募集しています!