📍

Mapbox Newsletter WEEKLY TIPSの解説 -「マーカーインスタンスにポップアップを添付」

2023/06/07に公開

はじめに

この記事は、本日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「マーカーインスタンスにポップアップを添付」についての解説です。また、Newsletterの購読はこちらからお申し込みいただけます。

コードを確認

まずExamplesのコードを見に行きましょう。

日本語サイト

英語サイト

基本的に同じコードですが、英語版はスタイルがMapbox Streets v12にアップグレードされているのでこちらを使用します。Mapbox Streets v11ではデフォルトのプロジェクションがWebメルカトルであるのに対し、Mapbox Streets v12ではGlobe(3D表示された地球)なので、印象がかなり異なります。

HTML/CSS

まずHTMLを見ていきましょう。以下は地図を表示するエレメントです。

<div id="map"></div>

次はCSSです。このサンプルではMarkerとPopupを使用しているため、それぞれCSSを設定します。以下はMarkerのCSSです。画像を使用し、角を丸めて円形にしています。

#marker {
  background-image: url('https://docs.mapbox.com/mapbox-gl-js/assets/washington-monument.jpg');
  background-size: cover;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  cursor: pointer;
}

以下はPopupのCSSです。このクラス名はサンプルコード中には出てきませんが、Popupクラス内部で使用されるクラス名です。Popupクラスは内部的にdivエレメントを作成し、それに対してmapboxgl-popupというクラス名を設定しています。詳細はこちらのコードをご参照ください。

.mapboxgl-popup {
  max-width: 200px;
}

Mapの作成

次にJavaScriptのコードを見ていきます。以下のコードはいつも通り、Mapオブジェクトを作成しています。containerで地図を表示するHTMLエレメントのidを指定します。

const map = new mapboxgl.Map({
  container: 'map',
  // Choose from Mapbox's core styles, or make your own style with Mapbox Studio
  style: 'mapbox://styles/mapbox/light-v11',
  center: monument,
  zoom: 15
});

Popupを作成します。setTextで文字列を指定すると、その文字列からテキストノードを作成し、divエレメントが作成されます。詳細はこちらのコードをご参照ください。また、オフセットを設定することで、PopupがMarkerに重ならないようにしています。

const popup = new mapboxgl.Popup({ offset: 25 }).setText(
  'Construction on the Washington Monument began in 1848.'
);

次にMarkerを作成します。ここではdivエレメントを明示的に作成し、Markerとして使用しています。idを指定して先程のCSSをあてています。これにより標準の青いピンではなく、CSSに設定されている画像がマーカーとして表示されます。また、後ほど説明しますがsetPopupメソッドでPopupオブジェクトと関連付けることで、Merkerクリック時にPopupを表示するといった連携動作が可能になります。

// create DOM element for the marker
const el = document.createElement('div');
el.id = 'marker';
 
// create the marker
new mapboxgl.Marker(el)
  .setLngLat(monument)
  .setPopup(popup) // sets a popup on this marker
  .addTo(map);

MarkerとPopupの連携

PopupはMarkerと連携することで利便性が増します。ここではMarkerのsetPopupメソッドとaddToメソッドの処理内容を確認し、どのようにMarkerとPopupが連携するのかを見てみます。

setPopup

Popupのoffset

以下のコードを見るとMarkerがデフォルト(水色のピン)のときは自動的にPopupのoffsetが設定されます。これはデフォルトを使用しているときはアイコンの高さが既知なのでPopupが重ならないoffsetが計算できるからですね。今回のサンプルでは独自のMarkerに変更しているので明示的にoffset: 25を設定しています。

Popupの座標の設定

以下のコードでPopupの座標を設定しています。そのため、Popup作成時に座標を設定する必要はありませんでした。

addTo

Popupのトグル

Markerをクリックすると自動的にPopupが表示されます。これは以下のコードでクリックイベント発生時にtogglePopupを実行しているためです。

togglePopupの処理は以下のとおりです。

const popup = this._popup;
if (!popup) {
    return this;
} else if (popup.isOpen()) {
    popup.remove();
    this._element.setAttribute('aria-expanded', 'false');
} else if (this._map) {
    popup.addTo(this._map);
    this._element.setAttribute('aria-expanded', 'true');
}

Popupが表示されていないときはPopup#addToを使用してMapオブジェクトに登録し、逆に表示されているときはPopup#removeで削除しています。

これにより、表示するときだけPopupのdivエレメントを作成し、非表示時にはエレメントそのものが削除されるので効率的です。

まとめ

このサンプルでは独自のMarkerの表示方法や、MarkerとPopupの連携方法について確認しました。

GitHubで編集を提案
マップボックス・ジャパン合同会社

Discussion