Google Maps PlatformのMaps JavaScript APIを使う機会があったのですが、とても簡単に複数マーカーをいい感じに表示できたので備忘録も兼ねて記事にしたいと思います。
ソースはここ
なお、API Keyは取得していることを前提として進めます。
取得がまだの方はここを参考にしてみてください。
Google Mapを表示させる
基本的にドキュメントを読めば簡単に表示させられます。
<div id="map"><!-- Google Map表示 --></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>
<script>
  function initMap() {
    // 日本の中央を表示する
    const defaultSettings = {zoom: 15, center: {lat: 40.804365, lng: 141.134867}};
    const map = new google.maps.Map(
      document.querySelector('#map'),
      defaultSettings
    );
  }
</script>
- Map表示用の
divを用意 - Maps JavaScript APIを読み込む(API keyを忘れずに)
 - callback関数の
initMapを定義 - Map表示用
divのDOMとズームレベルや初期表示位置を設定 
これだけ
API Key取得のほうが面倒ですね。
指定の場所にマーカーをつける
こちらも簡単です。
ドキュメント
// 表示データ
const data = [
  { name: "東京タワー", lat: 35.6585805, lng: 139.7454329 },
  { name: "京都タワー", lat: 34.9875441, lng: 135.7592164 },
  { name: "通天閣", lat: 34.6524992, lng: 135.5063058 }
];
function initMap() {
  // 省略
  // 現在表示されているinfoWindowオブジェクト
  let currentWindow;
  data.map(d => {
    // マーカーをつける
    const marker = new google.maps.Marker({
      position: {lat: d.lat, lng: d.lng},
      map: map
    });
    // マーカークリックしたら地名をポップアップさせる
    marker.addListener('click', () => {
      currentWindow && currentWindow.close();
      const infoWindow = new google.maps.InfoWindow({content: d.name});
      infoWindow.open(map, marker);
      currentWindow = infoWindow;
    });
  });
}
jsonをmapで回してMarkerオブジェクトを作ります。
せっかくなので、マーカーをクリックしたらその地名が表示されるようにました。
- 
Markerオブジェクトそれぞれにclickイベントを付与 - 既に開いている
infoWindowオブジェクトがあればそのwindowを閉じる - クリックされたマーカーの
infoWindowオブジェクトを作成してwindowを開く - 開いた
infoWindowオブジェクトを保存 
infoWindowオブジェクトを保持するのがちょっと不格好ですが、これ以外に方法がなさそうでした。
開いているwindowを取得できればいいのですが......
マーカーが画面上に収まるようにする
マーカーを表示できたのはいいのですが、画面に収まっていません。
そんなときはfitBoundsメソッドを使います。
引数には、LatLngBoundsクラスで範囲のインスタンスを渡してあげます。
LatLngBoundsの引数には緯度経度の最小値、最大値を渡します。
// マーカーがいい感じに表示できるよう調整
map.fitBounds(new google.maps.LatLngBounds(
  // sw
  {
    lat: Math.min(...data.map(d => d.lat)),
    lng: Math.min(...data.map(d => d.lng))
  },
  // ne
  {
    lat: Math.max(...data.map(d => d.lat)),
    lng: Math.max(...data.map(d => d.lng))
  }
));
ここで重要なのMapオブジェクトを作った際に指定したmaxZoomオプションです。
function initMap() {
  // 日本の中央を表示する
  const defaultSettings = {zoom: 15, /* これ */ maxZoom: 15, center: {lat: 40.804365, lng: 141.134867}};;
  const map = new google.maps.Map(
    document.querySelector('#map'),
    defaultSettings
  );
  // 以下省略
}
このオプションがないと、マーカーが1つだったり、マーカー同士が極端に近い場合、拡大されすぎて見栄えが悪くなってしまうんです。
動的に拡大率を変更する方法
基本的にfitBoundsやmaxZoomオプションで事足りると思いますが、何らかの条件をつけて拡大率を動的に変更しなければならない場合は以下のうようにします。
const listener = google.maps.event.addListener(map, 'idle', () => {
  // 実際には何らかの条件で拡大率を取得設定する
  map.getZoom() > 15 && map.setZoom(15);
  google.maps.event.removeListener(listener);
});
MapのイベントにaddListenerしてズームレベルを変えています。
なぜこんな面倒なことをしなければならないのか
実はfitBoundsを実行したあとは、setZoom()もgetZoom()も効かないのです。
how do I get the zoom level after fitBounds
google.maps.eventであれば何でもよさそうだったので、様々な処理が完了したタイミングで実行されるidleイベントで処理するようにしました。
バグなのか仕様なのかはわかりかねますが、拡大率が設定できない場合は、上記のうようにしてみてください。
