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 – 多角形を描く

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

 

Linux – 削除できません: 許可されていない操作です

Vagrantの共有ディレクトリーにホスト側のWindowsからディレクトリーをコピーしてmvやrmdirを実行しようとしたとき、以下のようなエラーになった。

rm: `...'を削除できません: 許可されていない操作です
rm: cannot remove `...': Operation not permitted

この場合、ディレクトリーのスティッキービットを外すことで通常通り削除が可能になる。

単一のディレクトリーのスティッキービットを外すには以下の通り入力。

ディレクトリー下に再帰的に行うには以下の通り入力。

 

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)。スライド方向は左上の方向。

 

地理院タイル

概要

国土地理院により、ラスタータイプのタイル地図が「地理院タイル」として提供されている。その仕様についてまとめてみた。

地理院タイルの考え方

地理院タイルは、地球全体をメルカトル投影により正方形化し、それがズームレベルに従って辺長1/2のエリアに分割されていく。

  1. 経緯度表現の全球をメルカトル投影により変換
  2. 投影後の形が正方形になるよう南北を制限
  3. 投影後正方形の地球全図をズームレベル0とする
  4. その後順次、同じ範囲に辺長を1/2の正方形が収まるよう分割

具体のタイル

具体の地理院タイルとタイル座標はタイル座標確認ページで確認できる。最小ズームレベル2で表示すると以下のように横長く表示されるが、正方形の世界全図が経度方向に繰り返されているのがわかる。

たとえば2/1/3のタイルの場合、ズームレベルが2、タイルのx座標、y座標がそれぞれ1、3ということになる。

ズームイン

ズームレベルを日本付近で上げていくと詳細な地図に変化していく。以下は首都圏付近のズームレベル9のタイル。首都圏中心部のタイルは454/201となっている。

最大ズームレベル18のタイルまで準備されている。以下は日本水準原点付近のタイルの例。

日本付近ではズームレベル18まで準備されているが、それ以外の地域で準備されているタイルはズームレベル8まで。以下は与那国島~台湾付近を順次拡大していった様子。

タイル座標

たとえばズームレベル2の場合、タイル座標は0/0~3/3、縦4×横4の16タイルで構成されている。ズームレベルが3になると、タイル座標は0/0~7/7、縦8×横8の64タイルで構成されている。

つまり、ズームレベルがzのとき、タイル座標は0~2z、タイルの枚数は2z×2z=22z枚ということになる。

タイルの取得

以下のURLを指定して、地理院サイトからタイル画像を取得することができる。

{t}は「データID」で、標準地図ならstd、単色地図ならpaleなどのコードが与えられている。{z}はズームレベル、{x}{y}はタイル座標値、{ext}は拡張子で、たとえば標準地図や単色地図ならpng

タイルピクセル

タイルサイズは、ズームレベルに関わらず256ピクセル×256ピクセルとなっている。

たとえばズームレベル2の場合は縦横256×4=1024ピクセルで構成され、ズームレベルが3になると縦横256×8=2048ピクセルでズームレベル2の時の倍のピクセル数となる。

一般にズームレベルzのとき、全球地図の縦・横のタイルピクセル数は256×2zとなり、ズームレベルが1つ上がるごとに倍になっていく。

タイル座標とタイルピクセル位置の関係

タイル座標とタイルピクセル位置の関係は、int(タイルピクセル位置/256)となる。そしてタイルピクセル位置からタイル座標値の256倍を引いた値(タイルピクセル位置を256で割った剰余)は、そのタイルピクセルを含むタイル内でのピクセルのオフセット位置になる。

たとえばズームレベル2の場合、(896, 448)のピクセルが属するタイルは3/1となり、このタイル内でのピクセルのオフセットは(128, 192)となる。