JavaScript

Googleマップに複数のピンを一括表示、全てが表示される縮尺にする

Googleマップに複数の住所を一括でプロット、かつ全てが表示される縮尺にする方法をご紹介します。事前に全ての住所が分かっている場合はコードの中でそれら住所を指定すればよいですが、そうもいかない場合もあります。

例としてやること

$shops_arrという変数に、東京駅、新宿駅、横浜駅の住所である以下の3つの住所が文字列で配列で格納されているとします。

どういうケースであってもよいですが、ユースケースの例として、WordPressのカスタムフィールドに入力された住所をプロットするというのが考えられます。配列に格納するまでの流れは、カスタムフィールドをプラグインなしで追加する方法カスタムフィールドの値を参照する方法(プラグインなし)の記事を続けて見てください。

$shops_arrに入っている住所をGoogleマップに表示します。

必要な準備

Google Cloud Platform(GCP)

この記事をここまで読んでいる方はすでに有効にされている方が多いかとは思いますが、まずGoogle Cloud Platformを始める必要があります。リンク先は私が書いた記事ですので、よろしければご参照ください。

Maps JavaScript APIの有効化

Maps JavaScript APIは、Googleマップをカスタマイズするのに必要なAPIです。GCPで「Maps JavaScript API」で検索すると出てくるので、そこで有効化できます。

Geocoding APIの有効化

Maps JavaScript APIは、住所と緯度経度情報の変換をするのに用いるAPIです。GCPで「Geocoding API」で検索すると出てくるので、そこで有効化できます。

コード(PHP+JavaScript)

<div id="map" style="width: 1000px; height: 500px;"></div> <!--widthとheightの値は自由-->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=【ここにAPIキー】&callback=initMap"></script> <!--googleのAPIを有効にする-->
<?php
   $shops_arr_json = json_encode($shops_arr); //jsonにしてJSに渡す
?> 
<script>
'use strict';
function initMap() {
   const addresses = <?php echo $shops_arr_json; ?>; // jsonにした配列を受け取り
   var bounds = new google.maps.LatLngBounds();
 
   var latlng = []; //緯度経度の値をセット
   var lat = []; //緯度の値をセット
   var lng = []; //経度の値をセット
   let maxLat = -90;
   let maxLng = -180;
   let minLat = 90;
   let minLng = 180;
   var marker = []; //マーカーの位置情報をセット
   let myLatLng; //地図の中心点をセット用
   let geocoder;
   geocoder = new google.maps.Geocoder(); // ジオコードリクエストを送信するGeocoderの作成
   const map = new google.maps.Map(document.getElementById('map'));//地図を作成する
   geo(aftergeo);
   function geo(callback){
       let cRef = addresses.length;
       for (let i = 0; i < addresses.length; i++) {
           (function (i) { 
               geocoder.geocode({'address': addresses&#91;i&#93;amp;}, 
                   function(results, status) { // 結果
                       if (status === google.maps.GeocoderStatus.OK) { // ステータスがOKの場合
                           lat&#91;i&#93; = results&#91;0&#93;.geometry.location.lat();//緯度を取得
                           lng&#91;i&#93; = results&#91;0&#93;.geometry.location.lng();//経度を取得
                           if( maxLat < lat&#91;i&#93; ){ maxLat = lat&#91;i&#93; }
                           if( maxLng < lng&#91;i&#93; ){ maxLng = lng&#91;i&#93; }
                           if( minLat > lat[i] ){ minLat = lat[i] }
                           if( minLng > lng[i] ){ minLng = lng[i] }
                           latlng[i]=results[0].geometry.location;// マーカーを立てる位置をセット
                           marker[i] = new google.maps.Marker({
                               position: results[0].geometry.location, // マーカーを立てる位置を指定
                               map: map // マーカーを立てる地図を指定
                           });
                       } else { // 失敗した場合
                       }//if文の終了
                       if (--cRef <= 0) {
                           callback();//全て取得できたらaftergeo実行
                       }
                       var sw = new google.maps.LatLng(maxLat, minLng);
                       var ne = new google.maps.LatLng(minLat, maxLng);
                       var bounds = new google.maps.LatLngBounds(sw, ne);
                       map.fitBounds(bounds); //複数マーカーをマップに表示させる
                   }//function(results, status)の終了
               );//geocoder.geocodeの終了
            }) (i);
         }//for文の終了
   }//function geo終了  
   function aftergeo(){
       let opt = {
           maxZoom: 15 // 地図の最大ズームを指定
       };
       map.setOptions(opt);//オプションをmapにセット
   }//function aftergeo終了
};//function initMap終了
</script>

これで、このように表示されます。

解説

以下がポイントだと思います。

  • PHPからJavaScriptに住所情報の配列をjson形式で渡す
  • 住所情報から緯度経度に変換
  • 緯度経度、それぞれ最大値と最小値を求める
  • 上記の最大値、最小値をもとに、Googleが用意している関数fitBoundsで複数の緯度経度すべてがマップ内に表示されるようにしている(50~53行目)

まとめ

地図を見てわかったことをまとめます。わかってはいたけど、東京駅と新宿の距離に比べて、横浜遠いですね・・
で、私の住む武蔵野市から横浜も遠いなと思ってるんですが、地図で見たら東京駅からと距離的に変わらないじゃないですか!なのに新宿か東京回って行かなきゃいけないんですけど。どなたか、どうにかできる方、どうにかしてください。

著者のイメージ画像

株式会社BringFlower
稲田 高洋(Takahiro Inada)

2003年から大手総合電機メーカーでUXデザインプロセスの研究、実践。UXデザイン専門家の育成プログラム開発。SEOにおいても重要なW3Cが定めるWeb標準仕様策定にウェブアクセシビリティの専門家として関わる。2010~2018年に人間中心設計専門家を保有、数年間ウェブアクセシビリティ基盤委員も務める。その後、不動産会社向けにSaaSを提供する企業の事業開発部で複数サービスを企画、ローンチ。CMSを提供し1000以上のサイトを分析。顧客サポート、サイト運営にも関わる。
2022年3月に独立後、2024年4月に株式会社BringFlowerを設立。SEOコンサルを活動の軸に据えつつ、AIライティングツールの開発と運営を自ら行う。グッドデザイン賞4件、ドイツユニバーサルデザイン賞2件、米国IDEA賞1件の受賞歴あり。