概要

ドキュメント Web applications

Mapbox を使ってウェブアプリケーションを作るというのはどういうことか、という説明がされる。最初に読むとよい。

vue-mapbpx

vue-mapbox

そこそこ使えそう。ユーザーは少ないが、作っている人がしっかりしている印象を受ける。

なぜ作ったのか、本人のブログ。非常に良い。

https://soal.red/reasoning-behind-vue-mapbox/

以下主にこのチュートリアルを中心に説明

公式のチュートリアル

  • マップ上にアイコンを配置する
  • アイコンをクリックすると移動する
  • 横のリストをクリックしても移動する

初期描画

ドキュメントのこのサンプルコードを参照

初期描画
// token を取得してセットする
mapboxgl.accessToken = 'pk.eyJ1IjoibmFrYW5pc2hpIiwiYSI6ImNqc3gwOGx0ejBuZ28zeXFqNmdtcmZta2IifQ.N7to3Ev75bjnH9O81Cun6w';

// mapboxgl.Map コンストラクターから map オブジェクトを作る
// その際、初期値として情報を渡す
// のちのちこの map オブジェクトに色々操作を加える
var map = new mapboxgl.Map({
  // map を紐づける DOM element 
  // id もしくは DOM element を指定する
  container: 'map',
  // よくわからない。自分でスタイルを作成できる模様。
  style: 'mapbox://styles/mapbox/light-v9',
  // 地図の中心地
  center: [-90.96, -0.47],
  // 拡大倍率 小数点以下も有効  12.6 とか
  zoom: 8
});

map がロードされた後にレイヤーの追加やイベントハンドラの追加を行うこと

ロード後にハンドラを追加すること
map.on('load', function () {
  // ここでもろもろ実行する
}

Geojson 情報からアイコン的なものを追加する

stores は次のような形式の単なる JS のデータ。これを source に紐づけることで、これを一気にマップに表示できる。id: 'locations' によってこのレイヤーの名前を定義する。これは後ほどイベントハンドラの追加等で使用する。

geojson 情報からアイコン的なものを追加する
map.addLayer({
    id: "locations",
    type: "symbol",
    // Add a GeoJSON source containing place coordinates and information.
    source: {
      type: "geojson",
      data: stores
    },
    layout: {
      // ここでアイコンの見た目を決めている模様
      "icon-image": "restaurant-15",
      "icon-allow-overlap": true
    }
  });

イベントハンドラを追加する

以下、onload 以降の実行内容に追加する。

アイコン的なものをクリックした時のイベントハンドラを追加する
// Center the map on the coordinates of any clicked symbol from the 'symbols' layer.
// 特定のレイヤーの feature がクリックされた時にだけハンドラを実行しているぽい
map.on("click", "symbols", function(e) {
  // e.features に 上記 stores の features の内容が入ってきている
  // しかし e には features というプロパティはなさそう謎
  
  // flyTo というマップの移動をするメソッドの中心地に利用している
  map.flyTo({ center: e.features[0].geometry.coordinates });
});

// Change the cursor to a pointer when the it enters a feature in the 'symbols' layer.

// canvas 上にあるマウスを変更することで擬似的にクリッカブルアイテム風に見せている
map.on("mouseenter", "symbols", function() {
  map.getCanvas().style.cursor = "pointer";
});

// Change it back to a pointer when it leaves.

// 同じく戻す
map.on("mouseleave", "symbols", function() {
  map.getCanvas().style.cursor = "";
});

イベントハンドラ追加する 他の例

とにかく map がクリックされるものを全てとる
map.on("click", function(e) {
  // Query all the rendered points in the view
  // queryRenderedFeatures メソッドで、ある地点近くにある feature を取ってこれるっぽい
  var features = map.queryRenderedFeatures(e.point, { layers: ["locations"] });
});

popup をつける

参考

currentFeature.geometry.coordinates に位置情報が入っているとする。

  • setLngLat で位置を指定
  • setHTML で描画する HTML を作る
  • addTo(map) でオブジェクトに追加する
popup をつける
var popup = new mapboxgl.Popup({ closeOnClick: false })
  .setLngLat(currentFeature.geometry.coordinates)
  .setHTML(
    "<h3>Sweetgreen</h3>" + "<h4>" + currentFeature.properties.address + "</h4>"
  )
  .addTo(map);

さらに高度で自由度の高いやり方

マーカーを画像とかにしたい場合、普通に HTML をブッコム。そのやり方。参照

基本的には DOM Element をマップに追加する。イベントリスナは普通にこの DOM にくっつける。

addLayer はやめて addSrouce で
// これは使わないので削除
map.addLayer({...})

// こっちで追加
map.addSource('places', {
  type: 'geojson',
  data: stores
});
Maler オブジェクトを使う
var el = document.createElement('div');
el.className = 'marker';

// eventListener を普通に DOM に追加する
el.addEventListener('click', function (e) {
  var activeItem = document.getElementsByClassName('active');
  // 1. Fly to the point
  flyToStore(marker);
  // 2. Close all other popups and display popup for clicked store
  createPopUp(marker);
  // 3. Highlight listing in sidebar (and remove highlight for all other listings)
  e.stopPropagation();
});

// el が DOM なので、DOM をマーカーとしてぶっこんで運用する
new mapboxgl.Marker(el, { offset: [0, -23] })
    .setLngLat(marker.geometry.coordinates)
    .addTo(map);

draggable の例

無理くりやってるっぽいやつ https://docs.mapbox.com/mapbox-gl-js/example/drag-a-point/

マーカー使う場合。こっちのほうが良さそう https://docs.mapbox.com/mapbox-gl-js/example/drag-a-marker/

Google の位置検索 API

渋谷駅 ラーメン とかで検索した結果を位置情報としてもらうには Google のやつのほうが良い。描画のみ Mapbox に担当させることにした。

https://developers.google.com/maps/documentation/geocoding/start