amay077
@amay077 (amay077)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

地図の Padding の初期値を指定できない問題

これは Mapbox Advent Calendar 2020 - Qiita の 12/9 の投稿です。1

Mapbox の地図領域には Padding を指定できます。
例えば地図の右側に凡例などをフローティングで表示させていたとき、その領域は避けて指定した領域を目一杯表示させたいときに便利です。

padding の指定は、Map.setPadding({...}) で全体指定するか、map.fitBounds(bounds, { padding: {...} }) のように表示位置を変えるメソッドに個別に指定するかの2択です。

Map.setPadding() は最初に一度設定しておけば、以降はその設定が維持されつづけるのですが、問題なのは「初期値」です。

コメントで教えて頂いた fitBoundsOptions で解決できました!

地図の初期表示位置は、

new mapboxgl.Map({
  container: 'map',
  bounds: [[sw.lng, sw.lat], [ne.lng, ne.lat]],
  

のように、地図インスタンスの生成時に範囲を指定することができますが、ここで padding を指定することはできません。

それならばと、インスタンス生成直後に map.setPadding() 呼び出しても効きません。

const map = new mapboxgl.Map({
  container: 'map',
  bounds: [[sw.lng, sw.lat], [ne.lng, ne.lat]],
  

map.setPadding({ top: 100, right: 100, bottom: 100, left: 100 }); // ←効かない

初期表示で padding を効かせた表示にするには、さらに map が load された後で fitBounds をし直す必要があるようです。

const map = new mapboxgl.Map({
  container: 'map',
  bounds: [[sw.lng, sw.lat], [ne.lng, ne.lat]],
  

map.setPadding({ top: 100, right: 100, bottom: 100, left: 100 }); // ←効かない

map.on('moveend', e => {
  console.log('moveend', map.getZoom()); // 2度呼ばれる
});

map.once('load', () => {
  map.fitBounds([[sw.lng, sw.lat], [ne.lng, ne.lat]], { animate: false }); // ここで Padding が効く
});

これはかなり微妙で、画面の表示時に地図が2度描画されていることになります(上記コードの moveend イベント参照)。
padding のサイズによっては、ユーザーにも2度描画されていることが確認されてしまうでしょう。

表示されている地図の「1ピクセルは何メートルか?」を計算する を使って、自力で padding(pixels) 分拡幅された bounds を指定することはできそうですが、面倒なのと、「1ピクセルは何メートルか?」も表示する地点によって変化するので一筋縄でいかなさそうです。

現状解決策は見えていません。良い方法があったら教えてください。
mapbox の issue に挙がっているかもしれませんし、もしかしたら前述の理由でそもそも不可能なのかもしれません。

であるとすると、padding を設定した後で fitBounds するまで地図の HTML要素を不可視にしておく、くらいしか策が無いのかもしれません。。。

コード


  1. 質問(意見交換) として投稿したらアドベントカレンダーへリンク貼ってくれなかった... 

0

期待した動作をするかはわかりませんが、fitBoundsOptionsというのが指定できるようですね。

const map = new mapboxgl.Map({
  container: 'map',
  bounds: bounds,
  fitBoundsOptions: { padding: { bottom: 150, top: 150, right: 150, left: 150 } },
  ...
});

A Map#fitBounds options object to use only when fitting the initial bounds provided above.

1Like

Your answer might help someone💌