Mapbox Newsletter WEEKLY TIPSの解説 -「ユーザーを探す」
はじめに
この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「ユーザーを探す」についての解説です。これはGeolocateControl
の使い方のサンプルです。また、Newsletterの購読はこちらからお申し込みいただけます。
以下が本サンプルのデモです。
ただし、上記デモはiframeで表示している(かつセキュリテイ設定が変更できない)関係上、動作しません。挙動を確認したい場合は以下のリンクをクリックして別タブで表示して試してください。また、CodePenもiframeを用いてコードを実行している関係上、ポリシーの問題でデバイスの向きを表す三角形の表示が出ません。完全な挙動を確認したい場合はExampleのページをご確認ください。
使い方
まず、地図右上のボタンをクリックします。
次にアドレスバーにダイアログが表示されるので、「許可する」をクリックします(初回のみです)。
しばらくすると現在位置にカメラが移動し、現在位置が丸い点で表示されます。
コードを確認
まずExamplesのコードを見に行きましょう。
日本語サイト
英語サイト
基本的に同じコードですが、英語版はスタイルがMapbox Streets v12にアップグレードされているのでこちらを使用します。Mapbox Streets v11ではデフォルトのプロジェクションがWebメルカトルであるのに対し、Mapbox Streets v12ではGlobe(3D表示された地球)なので、印象がかなり異なります。
HTML/CSS
まずHTMLを見ていきましょう。
以下は地図を表示するエレメントを作成しています。
<div id="map"></div>
Mapの作成
次にJavaScriptのコードを見ていきます。以下のコードはいつも通り、Mapオブジェクトを作成しています。container
で地図を表示するHTMLエレメントのidを指定します。
const map = new mapboxgl.Map({
container: 'map', // container ID
// Choose from Mapbox's core styles, or make your own style with Mapbox Studio
style: 'mapbox://styles/mapbox/streets-v12', // style URL
center: [-24, 42], // starting center in [lng, lat]
zoom: 1 // starting zoom
});
GeolocateControl
の追加
GeolocateControl
はIControl
を実装したものなので、Map#addControl
でマップに追加します。
map.addControl(
new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
// When active the map will receive updates to the device's location as it changes.
trackUserLocation: true,
// Draw an arrow next to the location dot to indicate which direction the device is heading.
showUserHeading: true
})
);
オプションの内容を確認します。
-
positionOptions
:GeolocateControl
はGeolocation APIを内部で使用していますが、そのGeolocation APIのgetCurrentPosition
のオプションに渡す値を指定します。ここではenableHighAccuracy: true
を設定しているので、可能な場合には詳細な現在位置が返されます。 -
trackUserLocation
:true
に設定すると、位置情報の更新に対して地図やポイントの位置を追従させます。デフォルトはfalse
です。 -
showUserHeading
:デバイスの向いている方向を三角形で表示します。デフォルトはfalse
です。ちなみにこの機能、当時マップボックス・ジャパンでテクニカルサポートエンジニアをされていたT Suzukiさんが実装したものです。
Android端末で動きを含めた挙動を確認すると以下のようになります。
まとめ
GeolocateControl
を用いてユーザの現在位置を表示する方法を確認しました。IControl
として実装されており、数行のコードで実現できることがわかりました。
おまけ
位置情報取得が成功すると自動的にカメラがコントロールされます。この仕組みについて見ていきます。
位置情報が取得されると、_onSuccess
が呼ばれます。この中の以下の部分でカメラのコントロールが行われます。
_updateCamera
では以下のような処理が行われています。
カメラのコントロールはfitBounds
で行われます。このメソッドはMapクラスの親クラスであるCameraクラスで以下のように定義されています。引数にLngLatBoundsLike
を取ります。これは矩形を[[左下],[右上]]
の形式で表現するデータ構造で、主に領域を表現するために使用します。つまりfitBounds
は引数として与えられた領域が表示されるようにカメラの座標やズームを適切にコントロールします。
さて、ここでは以下のように、取得した位置情報の中心座標(position.coords.longitude, position.coords.latitude
)および精度情報(position.coords.accuracy
)からtoBounds
を用いてLngLatBoundsLike
を算出しています。
const center = new LngLat(position.coords.longitude, position.coords.latitude);
const radius = position.coords.accuracy;
...
this._map.fitBounds(center.toBounds(radius), options, {
...
ということで、位置情報の座標・精度から適切にカメラがコントロールされているんですね。GeolocateControlのドキュメントの以下の記述内容も、これで納得です。
The zoom level applied depends on the accuracy of the geolocation provided by the device.
Discussion