a-blog cmsで現在地を中心に近隣の地図を表示するカスタマイズ

最近、位置情報で遊んでいて(いや、一応仕事です。記事は趣味ですが)、Entry_Geolistモジュールで現在地を中心に近隣のスポットを表示するカスタマイズをしてみました。

最近、位置情報で遊んでいて(いや、一応仕事です。記事は趣味ですが)、Entry_Geolistモジュールで現在地を中心に近隣のスポットを表示するカスタマイズをしてみました。

やり方を書いておかないと完全に忘れそうなので、完全に個人的な備忘録です。やや荒っぽくてほめられたものではなさそうなので、細かいところは自分で調べてください。

試してみたい方は、「テイクアウト東大阪」のトップページに表示される「現在地から探す」という、これ見よがしのボタンを押してみてください。そもそも位置情報が使えないという端末では、ボタンが表示されないのでご注意ください

クリックすると自分の今いる場所が中心になっている地図と、近隣のスポットの一覧が表示されます。

現在地を表示するグローバル変数を作る

まずEntry_Geolistですが、前提としてポストインクルード機能(post_include)で位置情報を取得して表示しますので、緯度と経度の情報を投げています。見た目にはURLは変わらないのですが、実は開発者ツールなどで見ると、こんな感じでテンプレートにパラメータが付けてられています。


画像:URLにパラメータが付けられている開発者ツールの画面

パラメータが付くということは、URLからグローバル変数を作れるんじゃない?ということで、%{NOW_LAT}と%{NOW_LNG}というグローバル変数を作りました。

これでJavaScriptの中に、地図の中心に現在地を変数で指定できるようになりました。

ちなみにa-blog cmsではGoogle Static Mapsを使って静的な地図を取得して、それを普通に操作ができる地図に変換したりしますが、今回はGoogle Maps JavaScript APIを使うことにしました。つまりJavaScriptで地図を設定して表示させるわけですね。

これにあたっては、TAMさんのブログ記事をコピペレベルでものすごく参考にしました。ありがとうございます。いつもお世話になっています。


マーカーの情報はEntry_GeolistをJavaScript内に書く

普通の使い方をしているとあんまりしないかもしれませんが、モジュールとか変数ってどこにでも書けます。今回はマーカーの情報をEntry_Geolistモジュールで出力しています。

var markerData = [{
  name: "現在地",
  lat: %{NOW_LAT},
  lng: %{NOW_LNG},
  pic: '',
  icon: '/images/map_current.png',
  }, <!-- BEGIN_MODULE Entry_GeoList id="map_geo_list" --><!-- BEGIN unit:loop --><!-- BEGIN entry:loop -->{
  name: "{title}",
  lat: {geo_lat},
  lng: {geo_lng},
  <!-- BEGIN_IF [{sliderImage@path}/nem] -->pic : '<img src="%{HTTP_ARCHIVES_DIR}{sliderImage@tinyPath}[resizeImg(160,90)]" alt="">',<!-- ELSE -->pic: '',<!-- END_IF -->
  }, <!-- END entry:loop --><!-- END unit:loop --><!-- END_MODULE Entry_GeoList -->
];

現在地だけはモジュールの外に出して、マップ上のピンもそこだけ変えています。

からまでがエントリーから持ってきたマーカーの情報になっています。各記事にはスライダーが付いていて、その1枚目の画像を吹き出しに表示させるようにしていますが、なんと校正オプションのリサイズも効きます。

画像がない場合には、picを空で出力しています。そうしないと未定義(undefined)になってしまうので。

こんな風にビルトインモジュールって、JavaScriptの中で動きますので、上手く使えばなんだってできそうな気がします。毎回気がするだけなのですが。

ポストインクルードでJavaScriptなんて動かないんじゃない?

既にお気づきかと思いますが、その通りです。動きません。

普通に地図を表示するだけとか、エントリーの持つ位置情報を使って、近いエントリーを表示するだけなら、モジュールを動かすだけでいいのですが、現在地を使うのであれば、ポストインクルードで1回投げる(表現合ってるのか?)必要があるのです。

読み込み先のテンプレートにJavaScriptを書いても動きませんし、元のページに書くと現在地のグローバル変数が使えないわけです。そして、それをごにょごにょする方法を私は知りませんし、調べても実装できる自信がありません。

そんなわけで2段階で読み込む

これを解決するために思いついたのがこちら。

まずポストインクルードでこんな感じでテンプレートを読み込みます。

<form action="" method="post" class="js-post_include" data-geo="true">
  <input type="hidden" name="tpl" value="/include/near_geo.html">
  <input type="hidden" name="bid" value="%{BID}" />
  <button type="submit" name="ACMS_POST_2GET" />周辺のスポットを探す</button>
</form>

現在地でEntry_Geolistを使う場合には formタグにdata-geo="true"を入れるのを忘れないようにしましょうね。

で、読み込んだ先のnear_geo.html(命名がどうとか、おとなげないことは言わないように)にはこんな風に書いています。

<iframe src="%{BLOG_URL}include/entry/near_geo2.html?lat=%{NOW_LAT}&lng=%{NOW_LNG}" frameborder="0"></iframe>

1回ポストインクルードで出力されていますので、このnear_geo.htmlではさっき作ったグローバル変数が使えます。いやー、無駄にならなくてよかった。

そして既に単体では表示できている地図のテンプレートを丸ごと読み込みます。この方法であれば、普通にファイルごと読み込みますので、Javascriptが動くかどうかは関係ありません。動きます。

多少強引なやり方ですが、現在地を中心にして、近隣のマップを表示させることができました。

元々のサイトが極めて狭い範囲の情報を扱っているので、東大阪に住んでいない人からは、単に自分いる場所が中心に表示されるだけかもしれませんが、サイトの内容とか距離感次第でズームを変えればいいだけです。

あまりほめられたやり方ではないかもしれませんが、グローバル変数を作ったと言っても、URLからパラメータを拾っただけで、数行のPHPを書いたくらいですし、基本的に標準機能とJavascriptくらいのことで、魔改造ではないはずです。

スマホで地図を使うなら、自分のいる場所を中心にして見たいじゃないですか

CMSの基本機能そのものをいじることはしたくないこと、たいした実装力がないことの2つの理由から、雑な感じの実装になってしまいましたが、前回の合宿で「今のモジュールじゃできないよ!」と言ったのですが、その時は解決方法が自分で見つけられなかったこともあり、自力で解決できたのでちょっとほっとしています。

もっとスマートな方法があると思いますが、きっと誰かが考えて次のa-blog cmsの合宿で発表してくれるので、それを待ちたいと思います。

丸1日空いてしまったので、うっかりとやってしまいました。
現場からは以上です(これ誰でしたっけ?)。