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
イベントで処理するようにしました。
バグなのか仕様なのかはわかりかねますが、拡大率が設定できない場合は、上記のうようにしてみてください。