Маска mapbox-gl карта с произвольным многоугольником
Я использую mapbox-gl и скачал векторные плитки с osm2vectortiles.org
Мне бы хотелось, чтобы карта была видна только в пределах известного многоугольника, и я не могу найти способ осуществить это.
Я могу представить несколько способов решения проблемы, и каждый путь привел меня к отсутствию ответов. Вот несколько подходов, которые я пытался исследовать:
- Какой-то слой маскировки карты. (Кажется, концепция не существует)
- Нарисуйте многоугольник и заполните его снаружи, а не внутри. (Кажется, вы можете только заполнить внутри полигонов)
- Нарисуйте заполненный прямоугольник вокруг внешних границ карты и вырежьте многоугольник. (Кажется, что функции MultiPolygon складываются вместо выреза)
- Модифицируйте mbtiles, притворяясь, что все, что находится за пределами многоугольника - это вода. ( https://github.com/mapbox/mbtiles-cutout показался многообещающим, но я не могу заставить его работать)
Как правильно подойти к этой проблеме?
1 ответ
Все упомянутые вами варианты могут работать. Вы можете вырезать исходные векторные данные так, чтобы они соответствовали области маски (как в варианте 4), или вы можете нарисовать слой маски поверх ваших данных (вариант 3).
Вот как вы можете сделать это со слоем маски:
https://jsfiddle.net/kmandov/cr2rav7v/
Добавьте вашу маску в качестве заливочного слоя:
map.addSource('mask', {
"type": "geojson",
"data": polyMask(mask, bounds)
});
map.addLayer({
"id": "zmask",
"source": "mask",
"type": "fill",
"paint": {
"fill-color": "white",
'fill-opacity': 0.999
}
});
Вы можете создать свою маску заранее (скажем, с помощью QGis или turf) или вы можете вырезать маску прямо в браузере, используя turf:
function polyMask(mask, bounds) {
var bboxPoly = turf.bboxPolygon(bounds);
return turf.difference(bboxPoly, mask);
}
var bounds = [-122.5336, 37.7049, -122.3122, 37.8398]; // wsen
var mask = turf.polygon([
[
[-122.43764877319336,
37.78645343442073
],
[-122.40056991577148,
37.78930232286027
],
[-122.39172935485838,
37.76630458915842
],
[-122.43550300598145,
37.75646561597495
],
[-122.45378494262697,
37.7781096293495
],
[-122.43764877319336,
37.78645343442073
]
]
]);
Возможно, вы хотели бы предотвратить выход пользователя за пределы маски, предоставив maxBounds
:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
center: [-122.42116928100586, 37.77532815168286],
maxBounds: bounds,
zoom: 12
});
Обратите внимание, что, кажется, есть ошибка, и вам нужно установить fill-opacity
что-то вроде 0.999