「お好みダムサーチ」の開発記

数ヶ月前から、自社プロダクトとしてWEB地図に関連した開発をしています。そのプロトタイプを友人に見せたところ、「自分はダムの地図が欲しい」と言われたので、頑張って作って「お好みダムサーチ」として公開しました。

http://maps.ontarget.cc/dams/

開発の経緯などは、(財)日本ダム協会運営のダム便覧に投稿しましたが(http://damnet.or.jp/cgi-bin/binranB/Konogoro.cgi?id=245)、ここでは技術面の紹介をします。

Google Maps APIのV3を使用

各種解説サイトなどを見ると、Google Maps API V2の使用例の方が豊富なのですが、Googleの公式サイトを見るとV2はすでに「obsolete」(要するにサポート終了)になっています。今から開発するのにobsoleteなものは使えないと思い、サンプルなどは見つかりにくいですが、V3を使うことにしました。

サンプルが少ないために、InfoWindow(マーカーをクリックしたときに出る吹き出し)の作成など、V2とV3で大きく仕様変更されている部分で多少苦労しましたが、後述するKML LayerなどのV3での新機能には助けられました。

堤高フィルタの刻み方へのこだわり

堤高フィルタのプルダウンメニューは、20m・30m・50m・80m・130mとしています。これは、フィボナッチ数列(ある項は直前の2つの項の和になっている1,2,3,5,8...という数列)の10倍です。ただし、堤高15m以上のものをダムと呼ぶことになっているので、最初の10mは除いています。

これは、単純に10mおきや20mおきにしてしまうと、プルダウンメニューが長くなってしまい、人間が使いやすい5個ぐらいまでにおさまらないので、このようにしました。

なお、他に倍々の数列を使う方法(20m・40m・80m・160m)もありますが、160mというフィルタがほとんど意味がなくなること(160mを超えるのは黒部ダム、高瀬ダム、徳山ダムの3つしかない)、160mを除いた3段階だと刻みが粗すぎることから、今回はフィボナッチ数列としました。

広域表示の方式について

ダムは、全国に約2,500個あります。とりあえず、通常サイズのアイコンで表示してみたところ、当たり前ですが意味不明でした(画像参照)。

そこで、広域表示を開発することにしました。たとえば、ポストマップ(http://postmap.org/map)は広域表示にすると、都道府県別のポストの登録数を表示するようになっています。ポストの場合、これで見ていて面白いのですが、ダムの場合は都道府県別の個数が見えてもあまり面白くなさそうです。

他にマーカーをまとめて表示する方法はないかと調べてみると、Google Maps APIの記事でいいものを見つけました。

http://code.google.com/intl/en/apis/maps/articles/toomanymarkers.html

クラスタリング系はどれも大差なく、ダムには向かなそうですが、Fusion Table Layerはなかなか良さそうです。これは、Googleのサーバに位置データを登録しておくと、リクエストがあったときに地図上にレンダリングした画像を生成して返してくれるサービスです。ただ、細かく見てみると、マーカーのデザインが自由に変更できない(プリセットされたものから選ぶだけ)なので、これは採用しませんでした。

完全カスタムのオーバーレイを合成するしかないかと不安になっていたら、KML Layerという機能があることに気付きました。KMLファイルを作成しておくと、Googleのサーバ上でレンダリングして地図の上に表示してくれる機能です。ダムのデータをKMLに変換して表示してみると、そこそこ快適だったので、最終的にこれを採用しました。

改めて見ていると、日本全体を表示したときなどは、さらに細かいアイコンの方がよさそうな気もします。「スーパーサマリーモード」を作ることも、いずれ検討しようと思っています。

2,500個のマーカーを軽快に表示するための工夫

さきほどのマーカーだらけの画像ですが、この状態からズームして、見かけ上表示されるマーカーを減らしても動作が遅く、しょっちゅう「このスクリプトの処理を中止しますか」というアラートが出ていました。これでは使い物にならないので、処理方法を変更することにしました。

まず、地図がドラッグされるたびに、中心から2,500個のダムまでの距離をすべて計算して、距離順にソートしている処理が遅いのかと疑い、複数のブラウザや5年前の遅いノートPCなどで、処理時間を計測してみましたが、数10msec程度しかかかっておらず、これが問題ではありませんでした(公開しているバージョンでもこの処理のままになっています)。

他にも色々な処理を疑って処理時間を計測してみたのですが、結局、作成するマーカー(表示するマーカーではなく)の個数が多いと重くなることが分かりました。

そこで、地図をドラッグするたびに、2,500個のダムに対して画面内に入るかどうかを調べて、毎回すべてのマーカーを作成してみました。動作は軽快になりましたが、ドラッグするたびに画面がちらつきます(マーカーの消去・描画を繰り返すため)。

ちらつきを防ぐために、最終的には、ドラッグするたびに、作成済みマーカーが画面内かどうかを調べて画面外になっているものは削除、全ダムに対して画面内かどうかを調べて画面内であってまだ作成マーカーが作成されていないものは作成、という処理に変更しました。

ドラッグするたびに、さきほどの距離計算と合わせてこんな処理までして、間に合うかどうか心配だったのですが、実装してみるとまったく問題なく動作しました。最近のPCとブラウザの処理能力には驚くばかりです。

サーバ設定による体感速度の改善

他にサーバ(Apache)の設定で、アイコン画像にはexpiresヘッダをつけることで、地図をドラッグしたときにいちいちサーバに画像を取りに行かないようにしたり、ファイルをgzip圧縮することで、ページを最初に表示する時間を短縮しています。

コンテンツのgzip圧縮というと、一般的にはApacheのmod_deflateを使うようですが、これはリクエストがあるたびに、コンテンツを毎回gzip圧縮します。「お好みダムサーチ」のコンテンツは、静的なものなので、これはCPUの無駄遣いと思い、あらかじめgzip圧縮したものをサーバに置き、ブラウザがgzip対応している場合にmod_rewriteを使ってそのファイルを送信するようにしました。

宣伝:地図サイトの受託開発やってます

この記事に書いたようなGoogle Maps API活用ノウハウを活かして、地図サイトの受託開発も承っています。詳しくは、会社サイトの受託開発の案内をご覧ください。