MapLibre – Popup

概要

クリック位置に地物(Feature)があれば、その属性をポップアップで表示する。ここでは地理院ベクトルタイルを表示させた地図に地物を表示させ、これらをクリックしたときにその属性を表示させている。

クリック時の地物の捕捉方法はこちらを参照。

実装例

内容

Popupには任意のHTMLを書けるが、ここではqueryRenderedFeaturesで取得した地物の属性を出力している。複数の地物が捕捉された場合、その分だけのポップアップが表示される。Popupは内容に合わせて幅や高さが調整される。

Popup生成時の引数で、クリック時の消去をfalseにして、スタイル設定用のHTMLクラス名を設定している。

その後、生成したPopupインスタンスの位置と表示内容をセットして、地図に貼り付けている。

ポップアップ内で桁を揃えるためのスタイルは、head要素内で定義している。

 

MapLibre – ソースの地物を捕捉する

概要

地図上でマウスクリックしてaddSourceaddLayerで表示した地物(Feature)を捕捉する。

  • FeatureCollectionの個々のFeature'properties'で属性を設定
  • map.on('click', ...)でマウスクリックを捕捉
  • クリック位置で地物を表示したレイヤ上の地物があれば、その属性等をコンソールに表示

実装例

内容

  • FeatureCollectionで2つのPointを定義し、それぞれのidとnameを属性として設定している
  • Pointのレンダリングは青い丸としている
  • クリック時のリスナーをmap.on('click', ...)で登録している
  • クリック位置のFeature群をqueryRenceredFeaturesで取得している
    • 第2引数で取得対象のソースがあるレイヤーを限定している
  • 取得したFeature群をforEachで1つずつ取り出して表示
    • このとき取り出した1つのfeatureundefinedでない場合だけ表示させている

 

MapLibre – GeoJSONのソースを描画する

基本形

  • Mapオブジェクトのonメソッドで、マップのロード後処理として記述する
  • MapオブジェクトのaddSourceメソッドで図形を定義し、addLayerメソッドでレンダリング方法などを記述する
  • addLayerでソースIDを指定する

addSource

  • 第1引数でソースIDを設定し、第2引数に図形のGeoJSONを記述する

addLayer

詳細はMapLibreのLayerのドキュメントを参照。

  • id:一意なレイヤーID
  • type:形状タイプ
    • 'fill', 'line', 'symbol', 'circle', 'heatmap', 'fill-extrusion', 'raster', 'hillshade', 'background'
    • 形状タイプごとの描画仕様は、その内容によってlayoutpaintで指定する
  • source:このレイヤーに描かれるソースのIDを指定
  • layout:形状タイプごとの描画スタイルを設定
    • たとえば'line'の場合、'line-width', 'line-cap', 'line-join'など
  • paint:図形を描く色などを指定
    • たとえば'circle'の場合、'circle-color', 'circle-radius'など

図形の描画例

 

MapLibre – 多角形を描く

1つの多角形を描く

多角形(’Polygon')は'coordinates'を多角形の頂点の3次元配列で与え、始点と終点で同じ座標とする。レイアウトの'type''fill'

以下の例では、ベクトルタイルの地理院地図上に3つの頂点を持つ三角形を描いている。'paint'で外枠の線を青、塗りつぶしの色を緑、塗りつぶしの不透明度を0.4としている。

dataで直接Polygonを指定できる。

複数の多角形を描く

以下の例ではaddSourceで2つのPolygonを描いている。addLayoutは上と同じものを使っており、addSourceaddLayermap.onメソッド内で実行させる。

'FeatureCollection'の代わりに直接'MultiPolygon'で書くと以下の通り。Polygonの場合は頂点の経緯度配列の3次元配列だったが、MultiPolygonの場合はさらにそれらの配列、4次元配列になる

これは折れ線の時と比べるとおかしく思えるが、後述のように1つの図形で複数の閉曲線を持つ場合があるためと考えられる。

捩じれたポリゴンは描けない

以下のように捩じれたポリゴンは描かれない。

ドーナッツは描ける

1つのフィーチャーで外側のポリゴンに内側のポリゴンが収まっていれば、描画方向に関わらずドーナッツのようなポリゴンになる。ただしドーナッツの穴の中にポリゴンを置くとうまく描かれない。

 

MapLibre – 折れ線を描く

1つの折れ線を描く

折れ線(LineString)は'coordinates'を折れ線の各点の2次元配列として与える。以下の例では、ベクトルタイルの地理院地図上に3つの点を結ぶ折れ線を描いている。レイアウトの'type''line'。線の色と太さは'paint'で設定し、'layout'では線の端部を丸く、折れ線の角を尖らせている。

dataで直接'LineString'を指定できる。

複数の折れ線を描く

以下の例ではaddSourceで2つのLineStringを描いている。addLayoutは上と同じものを使っており、addSourceaddLayermap.onメソッド内で実行させる。

'FeatureCollection'の代わりに直接'MultiLineString'で書くと以下の通り。LineStringの場合は通過点の経緯度の配列の2次元配列だったが、MultiLineStringの場合はさらにそれらの配列、3次元配列になっている。

 

MapLibre – 点を描く

1つの点を描く

以下の例では、ベクトルタイルの地理院地図の中央に1つの点を描き、そのスタイルを半径20の青い丸と設定している。

dataで直接'Point'を指定できる。

複数の点を描く

以下の例ではdata'type''FeatureCollection'として2つの点を描いている。点を青い丸で描くレイアウトは上と同じ。

'FeatureCollection'の代わりに直接'MultiPoint'で描くと以下の通り。Pointのときは経度・緯度を要素とする配列だったが、MultiPointの場合はそれらの2次元配列になっている。

 

MapLibre – MapBoxDrawによる描画機能

実装例

手順

  1. head要素内で以下を読み込む
    • turf.js:空間演算用のライブラリー(Turf.js)
    • mapbox-gl-draw.js
    • mapbox-gl-draw.css
  2. Mapオブジェクトを生成する
  3. MapboxDrawオブジェクトを生成する
  4. 生成したMapboxDrawオブジェクトをMapオブジェクトのコントロールとして追加する

MapBoxDrawコンストラクターのパラメーター

パラメーターなしの場合

パラメーターなしの場合、Line、Polygon、Point、trashとCombine、Uncombineのボタンが準備される。

パラメーターありの場合

表示されるボタンを選ぶことができる。

  1. displayControlsDefaultfalseにセット
  2. controlsの連想配列で必要なボタンをtrueにセット
    • line_string, polygon, point, trash, combine_features, uncombine_features

 

MapLibre – コントロールの追加と表示オプション

実装例

MapLibreの組込みコントロール追加方法。地理院地図ベクトルタイルでの表示例。

記述方法

mapMapインスタンスを参照しているとき、以下の形式で記述。

[コンストラクター]はコントロールのコンストラクターで、[位置指定]top-leftbottom-rightなど

コントロールの種類

NavigationControl
ズーム(+/−)とローテーションのボタン。ローテーションはボタン位置でドラッグすると地図が回転し、ダブルクリックで北が上の位置に戻る。
ScaleControl
スケールを表示する。スケール表示はズームレベルに合わせて変化する。
GeolocateControl
携帯端末などでユーザーの位置を扱う。

表示オプション

showTileBoundaries
trueにセットするとタイル境界を表示させる
showCollisionBoxes
trueにセットすると衝突によりラベルが表示されない場合も境界ボックスを描画する。

 

MapLibre – 表示の基本 – 地理院地図の例

基本形

有償となったMapBoxの代わりにオープンソースのMapLibreで地理院地図ベクトルタイルを表示する例。

要点は以下の通り。

  • 冒頭でサイトからライブラリーとスタイルを読み込むか、あらかじめダウンロードしておいたライブラリーを指定する
  • マップを表示するコンテナー要素を準備する
  • スクリプトでmaplibregl.Mapクラスのインスタンスを生成する
    • コンテナーに準備した要素のidを指定
    • 地理院地図のスタイルを指定
    • 地図表示の中心経緯度を指定~経度・緯度の順番なので注意
    • ズーム関係のパラメーターを指定

デフォルトでのマウス/キー操作

デフォルト設定では、以下のマウス操作が可能になっている。

  • ドラッグによる地図の移動
  • SHIFT+ドラッグによるボックスズームイン
  • CTRL+ドラッグによる回転と傾斜
  • ダブルクリックによるズームイン
  • SHIFT+ダブルクリックによるズームアウト

また、地図コンテナーにフォーカスがある状態で以下のキー操作が可能

  • カーソルキーによる地図の移動
  • SHIFT+←/→キーによる地図の回転
  • SHIFT+↑/↓キーによる傾斜

スタイルでソースを指定している

上記コードでは、表示させるターゲットの地理院地図ベクトルタイルが明示されていないが、実はターゲットとなるデータはstyleで示されるJSON中で指定されている。

styleで指定されたJSONの中を見てみると、sources属性のところに地理院サイトの提供URLのパターンがみられる。

Map生成時に指定する属性名はstyleだが、その中でaddSourceと同様に指定するターゲットや表示するレイヤーを指定している。

 

タイル画像のズームについて

概要

地理院タイルの画像を並べて表示し、ズームイン/ズームアウトの機能を実装したときの整理。マウスカーソルを置いた位置を固定して、そこを中心にズームイン/ズームアウトをするのにちょっと手間取った。

基本の考え方

共通する考え方は以下の通り。

  1. マウスクリック位置を記録する
  2. 拡大/縮小対象のタイルを拡大/縮小し、マウス位置もそれに合わせて変換
  3. 変換後の位置がマウス位置に重なるよう、タイルを平行移動

なお地理院タイルではタイルそのものを表す「タイル座標」を定義しているが、ピクセルの座標との区別を明確にするため、ここでは「タイルアドレス」と表現し、ピクセル単位の座標を「ピクセル座標」と表現する。

ズームインの場合

ズームインの場合、マウス位置がタイルの左側か右側か、上側か下側かによって拡大するタイルやスライドの方向・量が異なる。以下ではxとyがともに左・上、右・下のケースで整理しているが、xとyは独立に判定してよい。

マウス位置がタイルの幅/高さの半分未満の時

下図の緑色のタイルが現在表示されているタイルでタイルの幅をw、高さをhとする。また黒い点(x, y)をマウス位置とする。位置(x, y)はタイル左上の点からのオフセットで表しているが、タイルを表示するcanvasなどの座標に相当する。

タイルアドレスをr/cとして、マウス位置がタイルの幅/高さの半分より左/上の場合を考える。拡大するタイルはr/cに対して青いタイル2r/2cで、拡大前の幅w/2、高さh/2が2倍になり、元のタイルと同じサイズになる。

拡大後のタイルでは、マウス位置(x, y)にあった地上の位置はタイルの拡大につれて(2x, 2y)となる。マウス位置(x, y)は拡大後のタイル上でも同じ。

拡大後の地上の位置を元の位置に合わせるためタイルをスライドさせる。スライド量は(2x, 2y)と(x, y)の差(x, y)で、スライド方向は左上の方向。

マウス位置がタイルの幅/高さの半分以上の時

元のタイルr/cに対して拡大するタイルは2r+1/2c+1となる。また、拡大するタイル内での地上位置のオフセットは(x – w/2, y – h/2)となる。

タイルを拡大すると、地上の位置のオフセットは(2x – w, 2y – h)となる。マウス位置は(x, y)のまま。

地上の位置をマウス位置に合わせるためタイルをスライドさせる。スライド量は(x, y)と(2x – w, 2y – h)の差で(w – x, h – y)。スライド方向は右下の方向。

ズームアウトの場合

ズームインの場合、タイルアドレスが偶数か奇数かによって縮小するタイルやスライドの方向・量が異なる。以下ではxとyがともに偶数/基数のケースで整理しているが、xとyは独立に判定してよい。

タイルアドレスが偶数の場合

緑色のタイルが現在表示されているタイルで、アドレスが偶数の場合、縮小するタイルは右/下方向に広がった青いタイルr/c。その幅・高さは2w、2cから半分のw、cとなる。サイズが半分になる前の地上位置のオフセットは、(x, y)。

ここではタイルのサイズを上の図の2倍のサイズで描いている。タイル縮小後の元の位置は、タイル幅/高さが1/2になるのに伴って(x/2, y/2)となる。マウス位置(x, y)は元のまま。

地上の位置をマウス位置に合わせるためタイルをスライドさせる。スライド量は(x, y)と(x/2, y/2)の差で(x/2, y/2)。スライド方向は右下の方向。

タイルアドレスが奇数の場合

緑色のタイルが現在表示されているタイルで、アドレスが奇数の場合縮小するタイルは左/上方向に広がった青いタイルr/c。縮小するタイル上での縮小前の地上位置のオフセットは(x + w, y +h)

ここではタイルのサイズを上の図の2倍のサイズで描いている。タイル縮小後の元の位置は、タイル幅/高さが1/2になるのに伴って((x + w)/2, (y + h)/2)となる。マウス位置(x, y)は元のまま。

地上の位置をマウス位置に合わせるためタイルをスライドさせる。スライド量は((x + w)/2, (y + h)/2と(x/2, y/2)の差で((w – x)/2, (h – y)/2)。スライド方向は左上の方向。