🐈

Mapbox Newsletter WEEKLY TIPSの解説 -「マーカーでカスタムアイコンを追加」

2023/10/12に公開

はじめに

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

コードを確認

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

日本語サイト

英語サイト

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

HTML/CSS

CSSではマーカーのスタイルを定義しています。border-radius50%なので、丸い表示になります。

.marker {
  display: block;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
}

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

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

GeoJSONの定義

次にJavaScriptのコードを見ていきます。まず、GeoJSONを定義しています。Pointデータが3個あり、それぞれプロパティとしてmessageiconSizeを持ちます。

const geojson = {
  'type': 'FeatureCollection',
  'features': [
    {
      'type': 'Feature',
      'properties': {
        'message': 'Foo',
        'iconSize': [60, 60]
      },
      'geometry': {
        'type': 'Point',
        'coordinates': [-66.324462, -16.024695]
      }
    },
...

Mapの作成

以下のコードはいつも通り、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/streets-v12',
  center: [-65.017, -16.457],
  zoom: 5
});

マーカーの作成

ループ

先程定義したGeoJSONのfeaturesでループを回します。featuresにはPointデータが3個入っていたので、各Pointデータについて処理することになります。

for (const marker of geojson.features) {
  ...
}

divエレメントの作成

ループの中身を見ていきます。まずdivエレメントを作成し、幅・高さをGeoJSONのプロパティから取得します。更にクラスは先程CSSで定義したものを使用します。今回のテーマであるカスタムアイコンはhttps://placekitten.com/g/から取得し、backgroundImageとしています。

// Create a DOM element for each marker.
const el = document.createElement('div');
const width = marker.properties.iconSize[0];
const height = marker.properties.iconSize[1];
el.className = 'marker';
el.style.backgroundImage = `url(https://placekitten.com/g/${width}/${height}/)`;
el.style.width = `${width}px`;
el.style.height = `${height}px`;
el.style.backgroundSize = '100%';

ちなみに、各サイズの画像は以下のとおりです。

クリックイベント

divエレメントがクリックされた際にalertを表示します。メッセージはGeoJSONのプロパティを使用します。

el.addEventListener('click', () => {
  window.alert(marker.properties.message);
});

マーカーの作成

最後にマーカーを作成します。Markerクラスのコンストラクタは第一引数としてoptionを取りますが、HTMLエレメントが指定された時には内部的にoption.elementに置き換えます。したがって、オプションとしてエレメントだけを指定する場合はサンプルのように直接パラメータとして指定しても良いですし、他にもオプションを指定したい場合にはoptions.elementとして指定します。また、HTMLエレメントを指定しない場合はデフォルトの青いマーカーがdivエレメントとして内部的に作成されます。

あとはGeoJSONから座標を取得しmapオブジェクトにaddToすることで表示されます。

// Add markers to the map.
new mapboxgl.Marker(el)
  .setLngLat(marker.geometry.coordinates)
  .addTo(map);

まとめ

マーカーは地図の要素ではなくHTMLエレメントとして作成されます。そのため、通常のHTML/CSSのテクニックでカスタムアイコンを指定できます。

マーカーの使い方については以下の記事もご参照ください。

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

Discussion