Unit_List の使用ケースその2:Google MapのAPI 「MarkerClusterer」

エントリー内のユニットを表示するUnit_Listの使用ケース紹介その2では、Google MapのAPI 「MarkerClusterer」を使ったUnit_Listの活用方法をご紹介します。

たとえば、1つの地図に各エントリーに1つずつ挿入されている地図ユニットをピンでまとめたいときに有効です。

MarkerClustererを使うことにより、同じ位置にエントリーが集中していたとしてもピンが多くなりすぎず、すっきりとした見た目になります。


遠くのエントリーは1件表示だけですが、近くの2件はまとめて表示される

3件のエントリーに1つずつ地図が入力されている場合の MarkerClusterer の例


実装方法

/js/makerclusterer.jsと/images/フォルダをGitHubよりダウンロードしてください。

ソースコード:headタグ

headタグ内に以下を記述してください。

<script type="text/javascript" src="https://maps.google.com/maps/api/js?key=%{GOOGLE_API_KEY}&sensor=false"></script> 
<script type="text/javascript" src="/js/markerclusterer.js"></script>

テーマフォルダに/images/フォルダを設置するときは、/js/makerclusterer.jsの以下の記述のパスを変更する必要があります(例: '/theme/site/images/m'; など)。

MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_ = '../images/m';

ソースコード:MarkerClustererを設置したい場所への記述

HTMLファイル内のMarkerClustererを設置したい場所に以下を記述します。

<div id="map" style="height: 400px;"></div>

ソースコード:地図の基準にしたい緯度経度の情報を登録するカスタムフィールド

ブログのトップに表示させたい場合はブログのカスタムフィールドに、カテゴリーの一覧に表示させたい場合はカテゴリーのカスタムフィールドに記述してください。

※Site2016内の/admin/category/field_realestate.htmlと同じ内容です

<h3 class="acms-admin-admin-title2">一覧ページで表示させる地図の中心の緯度経度設定</h3>
<table class="adminTable acms-admin-table-admin-edit">
<tr>
  <th>地図</th>
  <td class="js-map-editable">
    <div class="acms-admin-form-group">
      <label for="input-text-map-search_text" class="acms-admin-hide-visually">住所で検索する</label>
      <input type="text" name="" value="" id="input-text-map-search_text" class="js-editable_map-search_text" disabled="disabled" size="40" />
      <input type="button" name="" value="検索" class="js-editable_map-search_button acms-admin-btn-admin" disabled="disabled" />
    </div>
    <div class="acms-admin-form-group">
      <img class="js-map_editable-container" src="http://maps.google.com/maps/api/staticmap?center={index_map_lat},{index_map_lng}&zoom={index_map_zoom}&size=640x400&maptype=roadmap&markers={index_map_lat},{index_map_lng}&key=%{GOOGLE_API_KEY}" width="640" height="400" style="display:block;" />
    </div>
  <!-- BEGIN index_map_lat:veil -->
  <label for="input-text-index_map_lat">緯度</label> <input type="text" name="index_map_lat" value="{index_map_lat}" size="9" id="input-text-index_map_lat" class="js-map_editable-lat" />
  <label for="input-text-index_map_lng">経度</label> <input type="text" name="index_map_lng" value="{index_map_lng}" size="10" id="input-text-index_map_lng" class="js-map_editable-lng" />
  <label for="input-text-index_map_zoom">ズーム</label> <input type="text" name="index_map_zoom" value="{index_map_zoom}" size="10" id="input-text-index_map_zoom" class="js-map_editable-zoom" />
  <!-- END index_map_lat:veil -->
  <!-- BEGIN index_map_lat:empty -->
  <label for="input-text-index_map_lat">緯度</label> <input type="text" name="index_map_lat" value="35.172775" size="9" id="input-text-index_map_lat" class="js-map_editable-lat" />
  <label for="input-text-index_map_lng">経度</label> <input type="text" name="index_map_lng" value="136.887466" size="10" id="input-text-index_map_lng" class="js-map_editable-lng" />
  <label for="input-text-index_map_zoom">ズーム</label> <input type="text" name="index_map_zoom" value="7" size="10" id="input-text-index_map_zoom" class="js-map_editable-zoom" />
  <!-- END index_map_lat:empty -->
  <input type="hidden" name="field[]" value="index_map_lat" />
  <input type="hidden" name="field[]" value="index_map_lng" />
  <input type="hidden" name="field[]" value="index_map_zoom" />
  </td>
</tr>
</table>

ソースコード:MarkerClustererを動かすためのJavaScript(ここではHTMLファイルとして使用します。例:map.html)

<script type="text/javascript">
  var map = null;
  var markerclusterer = null;
  var infowindow = new google.maps.InfoWindow();
  var gmarkers = []; 
  // マーカーの作成と、吹き出しの作成
  function createMarker(latlng, info) {
    var marker = new google.maps.Marker({
      position: latlng,
      map: map
    });
    google.maps.event.addListener(marker, 'click', function() {
      infowindow.setContent(info); 
      infowindow.open(map,marker);
    });
    // 情報を保存
    gmarkers.push(marker);
  }
  // クリックイベントを作成する
  function myclick(i) {
    google.maps.event.trigger(gmarkers[i], "click");
  }
  function initialize() {
    // 全体の地図を作成
    <!-- BEGIN_MODULE Category_Field -->
    var myOptions = \{
      zoom: {index_map_zoom},
      center: new google.maps.LatLng({index_map_lat},{index_map_lng}),
      mapTypeControl: true,
      navigationControl: true,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    \}<!-- END_MODULE Category_Field -->
    map = new google.maps.Map(document.getElementById("map"), myOptions);
    google.maps.event.addListener(map, 'click', function() {
      infowindow.close();
    });
    // 場所・吹き出しの情報を定義
    var markers = [
    <!-- BEGIN_MODULE Unit_List id="map" --><!-- BEGIN unit:loop -->
      ["{entry_title}", {unit_field_2},{unit_field_3},"{entry_url}"],<!-- END unit:loop -->[]<!-- END_MODULE Unit_List -->
    ];
    // 吹き出しに入れる要素
    for (var i = 0; i < markers.length; i++) {
      var point = new google.maps.LatLng( markers[i][1],  markers[i][2]);
      var marker = createMarker( point, "<div class='scrollFix'><p class='mapEntryTitle'>" + markers[i][0] + "</p> " + "<p class='mapDetailInfo'>緯度: " + markers[i][1] + "<br> 経度: "  +  markers[i][2] + "</p><p class='mapLinkText'><a href='"+ markers[i][3] +"'>詳しく見る</a></p>" + " </div>") ;
    }
    markers.pop();
    // 地図を表示
    markerCluster = new MarkerClusterer(map, gmarkers);
  }
  window.addEventListener('load', initialize);
</script>

注意点

  • 「MarkerClustererを動かすためのJavaScript」のソースコードは、全てJavaScriptで書かれていますが a-blog cms のモジュールを使っているためHTMLファイル内に記述します
  • 25行目ではCategory_Fieldを使用していますが、もし「地図の基準にしたい緯度経度の情報を登録するためのカスタムフィールド」をカテゴリー以外のカスタムフィールドとして設置した場合、対応するフィールドモジュールに置き換えます

モジュールIDの設定

モジュールID名「map」というUnit_Listのモジュールを作ります。


ユニットタイプの「地図」がチェックされていることを確認してください。

そのほかの設定については、必要に応じて有効にしてください。

マップ比較(Google Map・OpenStreetMap・MapBox)


a-blog cms では OpenStreetMap と Google Map が標準で実装されています。それぞれのサービスの特徴について調べましたのでサイト制作時のお役に立てればと思います。(2020/02時点)

簡単な比較表

最近話題に上がっている MapBox も合わせて比較してみました。



OpenStreetMap Google Map MapBox
a-blog cms 標準実装か 標準実装 標準実装 標準実装でない
料金 無料 月28,571PVまで無料 月50,000リクエストまで無料
各サービスサイトでの設定 なし 必須 必須
クレジットカードの登録 なし 必須 ひとまず載せるだけなら必須でない
認知度 あまり知られていない 高い あまり知られていない

※ Google Map の料金計算は月間10万ロード以下の場合で Maps JavaScript API を使用していると仮定した値段です。使用するAPIや条件で料金は変わってきます。
Maps JavaScript API Usage and Billing | Google Developers

※ MapBox の料金計算は Maps Loads for Web を使用していると仮定した値段です。使用する機能や条件で料金は変わってきます。
Mapbox 料金

地図の表示比較

3つの地図を並べてみました。Google Map と MapBox は特殊なオプションをつけていないものになります。

OpenStreetMap



メリット

  • 無料

デメリット

  • 認知度が低い
  • お店情報が少ない

a-blog cms では標準が OpenStreetMap であるため見たことがある人も多いと思います。
OpenStreetMap は、オープンソースで作られている地図サービスになります。誰でも自由に参加して、誰でも自由に地図を編集して、誰でも自由に地図を利用することが出来ます。そのためメンテナンスが盛んな場所もあれば古いままの場所も出てきてしまいます。名古屋周辺で確認したところ古い情報のままのお店などを確認することができました。

Google Map



メリット

  • 認知度が高い
  • お店情報が豊富
  • ストリートビューを見れる

デメリット

  • クレジットカード登録が必須
  • 値段がやや高い

Google Map は認知度が高く、日本でも広く使われています。また、お店情報も豊富です。
他の地図には無い機能として「ストリートビュー」も強みだと思います。 a-blog cms では Google Map ユニットに標準でストリートビュー切り替え機能を搭載していますので簡単に導入することが可能です。 しかし、クレジットカード登録をしないと使用できないため、サイト制作時に試しに Google Map を載せたいという時も一手間かかります。 MapBox と比べると値段がやや高いため、Webサイトにあまりコストをかけたく無い場合は他の地図を検討する必要があります。

MapBox



メリット

  • 公式ページのMap導入方法解説ページが優しい
  • 地図スタイルのカスタマイズが細かくできる

デメリット

  • a-blog cms標準機能でない
  • 認知度が(まだ)低い
  • お店情報が(まだ)少ない

a-blog cms ではまだ標準機能としての搭載には至っておりません。静的なテンプレートに地図を貼り付けるだけであれば数十行のカスタマイズで可能ですが、カスタムフィールドやユニットに組み込むにはさらにひと手間かかります。 また、MapBox が日本向けにサービス提供したのが2019年のためまだ認知度が低く、 Google Map ほどお店情報も豊富ではありません。しかし、 Mapbox の地図データはユーザの携帯電話から送信されるGPS情報を元に作成されるようなので今後使用ユーザーが増えるほど地図の精度もあがってくのではないでしょうか。

「Mapboxの地図データはユーザの携帯電話から送信されるGPS情報を元に作成されています。ユーザがMapboxの地図を起動すると、緯度、経度、時刻などの情報がプライバシーに配慮したプロセスを経て、自動でMapboxに送信されます。
こうして集まったデータによりMapboxの地図データはリアルタイムでアップデートされているのです。ユーザデータを利用することで、顧客企業に精密な地図データを低コストで導入いただけるようになりました」(デイブ・コール氏)

引用:https://www.softbank.jp/biz/future_stride/entry/technology/20200131/

a-blog cms の標準機能ではないですが、ただ地図を載せるだけであれば簡単に導入できます。上記 MapBox 地図のソースコードは20行もありません。

<div class="column-map-centter js_notStyle acms-col-sm-12">
  <div id='map' style='width: 775px; height: 516px;'></div>
</div>
<script>
  mapboxgl.accessToken = 'アクセストークンキー';
  var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [136.88741, 35.17291],
    zoom: 16
  });
  var marker = new mapboxgl.Marker()
  .setLngLat([136.88741, 35.17291])
  .addTo(map);
</script>

導入方法については公式サイトで優しく案内してくれるので気になる方は MapBox のアカウントを作成してみてください。

MapBox Japan
https://www.mapbox.jp/

マップスタイルのカスタマイズはブラウザ上で行えます。画面上で確認をしながらフォントの設定やマップの配色などの細かい調整が可能です。