Mapbox GL JS getBounds()/fitBounds() 函数
Mapbox GL JS getBounds()/fitBounds()
我正在使用 Mapbox GL JS v0.14.2,并且我通过文档进行了高低搜索,对此知之甚少。
如果您使用标准 JS API,使用他们提供的示例 (https://www.mapbox.com/mapbox.js/example/v1.0.0/fit-map-to-markers/); however the setup when using the GL api is quite different. The GL API has getBounds()
(https://www.mapbox.com/mapbox-gl-js/api/#Map.getBounds) 'fit map to markers' 就很清楚了,但是因为您没有命名层,就像标准的 JS API,所以我正在努力研究如何使用 getBounds()
。
我找到了这个 () 但肯定不是正确答案?
这是我的大部分设置;不包括 JSON 设置和其他选项。
mapboxgl.accessToken = '<myaccesstoken>';
var markers = <?php echo $programme_json; ?>;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/richgc/cikyo5bse00nqb0lxebkfn2bm',
center: [-1.470085, 53.381129],
zoom: 15
});
map.on('style.load', function() {
map.addSource('markers', {
'type': 'geojson',
'data': markers
});
map.addLayer({
"id": "markers",
"interactive": true,
"type": "symbol",
"source": "markers",
"layout": {
"icon-image": "venue-map-icon-blue",
'icon-size': 0.5,
"icon-allow-overlap": true
}
});
map.scrollZoom.disable();
});
我试过以下方法:
alert(map.getBounds()); // LngLatBounds(LngLat(-1.4855345239256508, 53.37642500812015), LngLat(-1.4546354760740883, 53.38583247227842))
var bounds = [[-1.4855345239256508, 53.37642500812015],[-1.4546354760740883, 53.38583247227842]]
map.fitBounds(bounds);
所以我知道如何 fitBounds,但我不确定如何获得它们 map.getBounds()
似乎 return 设置的中心位置 lng/lat。
标记 JSON:
var markers = {"type":"FeatureCollection","features":[{"type":"Feature","properties":{"title":"Site Gallery","url":"\/Freelance\/art-sheffield-2016\/programme\/site-gallery\/","summary":"Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Donec id justo. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Suspendisse feugiat. Etiam rhoncus.","image":"\/Freelance\/art-sheffield-2016\/site\/assets\/files\/1032\/site_gallery.jpg","marker-symbol":"venue-map-icon-blue","colour":"blue"},"geometry":{"type":"Point","coordinates":["-1.466439","53.376842"]}},{"type":"Feature","properties":{"title":"Moore Street Substation","url":"\/Freelance\/art-sheffield-2016\/programme\/moore-street-substation\/","summary":"","image":null,"marker-symbol":"venue-map-icon-green","colour":"green"},"geometry":{"type":"Point","coordinates":["-1.477881","53.374798"]}},{"type":"Feature","properties":{"title":"S1 Artspace","url":"\/Freelance\/art-sheffield-2016\/programme\/s1-artspace\/","summary":"","image":null,"marker-symbol":"venue-map-icon-red","colour":"red"},"geometry":{"type":"Point","coordinates":["-1.459620","53.380562"]}}]};
Mapbox 自己的 geojson-extent plugin will do the trick. Assuming your markers
object is valid GeoJSON,你可以简单地将它传递给 geojsonExtent()
函数来获得一组边界,然后你可以传递给 fitBounds()
.
加载 geojson-extent.js 文件后(例如,通过在 HTML 代码中使用 <script>
标记),您应该能够执行此操作以使您的地图适合GeoJSON markers
对象的边界:
map.fitBounds(geojsonExtent(markers));
更新
GeoJSONLint 报告您的 markers
对象不是有效的 GeoJSON,因为每个位置的元素都被解释为字符串,而不是数字。如果你从 lon-lat 坐标中删除引号,它应该可以正常工作:
var markers = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "Site Gallery",
"url": "\/Freelance\/art-sheffield-2016\/programme\/site-gallery\/",
"summary": "Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Donec id justo. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Suspendisse feugiat. Etiam rhoncus.",
"image": "\/Freelance\/art-sheffield-2016\/site\/assets\/files\/1032\/site_gallery.jpg",
"marker-symbol": "venue-map-icon-blue",
"colour": "blue"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.466439,
53.376842
]
}
},
{
"type": "Feature",
"properties": {
"title": "Moore Street Substation",
"url": "\/Freelance\/art-sheffield-2016\/programme\/moore-street-substation\/",
"summary": "",
"image": null,
"marker-symbol": "venue-map-icon-green",
"colour": "green"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.477881,
53.374798
]
}
},
{
"type": "Feature",
"properties": {
"title": "S1 Artspace",
"url": "\/Freelance\/art-sheffield-2016\/programme\/s1-artspace\/",
"summary": "",
"image": null,
"marker-symbol": "venue-map-icon-red",
"colour": "red"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.459620,
53.380562
]
}
}
]
};
如果您想使地图适合标记,您可以创建包含所有标记的边界。
var bounds = new mapboxgl.LngLatBounds();
markers.features.forEach(function(feature) {
bounds.extend(feature.geometry.coordinates);
});
map.fitBounds(bounds);
对于适用于所有 GeoJSON 对象的解决方案,而不仅仅是一组标记,请查看 Mapbox 的 Turf.js。
这段代码对我很有帮助:https://bl.ocks.org/danswick/83a8ddff7fb9193176a975a02a896792
但只是重复基础知识以防 link 死亡:
var bounds = turf.bbox(markers);
map.fitBounds(bounds, {padding: 20});
linked 代码中提到的 extent
方法已被弃用,取而代之的是 bbox
,但结果是一样的。
这是我基于 Mapbox example.
的 reduce 操作的解决方案
它适用于包含点特征和多点特征(如线)的 geojson。
let bounds = geoJSON.features.reduce(function(bounds, feature) {
if(!Array.isArray(feature.geometry.coordinates[0])) { // point feature
return bounds.extend(feature.geometry.coordinates);
} else {
return feature.geometry.coordinates.reduce(function(bounds, coord) {
return bounds.extend(coord);
}, bounds);
}
}, new mapboxgl.LngLatBounds());
map.fitBounds(bounds, {
maxZoom: 12,
padding: 30, // in px, to make markers on the top edge visible
})
如果这里有人在使用 React-Map-GL,有两个以上的标记,并且想计算 before 的边界加载地图并检索 Mapbox 实例,您可以这样做:
const lat = myCoordinatesArray.map(location => parseFloat(location.lat));
const lng = myCoordinatesArray.map(location => parseFloat(location.lng));
// Note that WebMercatorViewport requires this format [lng, lat]
const minCoords = [Math.min.apply(null, lng), Math.min.apply(null, lat)];
const maxCoords = [Math.max.apply(null, lng), Math.max.apply(null, lat)];
const formattedGeoData = [minCoords, maxCoords];
const vPort = new WebMercatorViewport(this.state.viewport).fitBounds(formattedGeoData, {
padding: 100
});
const { latitude, longitude, zoom } = vPort;
来源:
您可以在渲染函数之前以构造函数的方式完成所有这些,并为插件初始化获取您的值。
改进的解决方案(基于@timur 解决方案)通过使用 while 循环和 promise
来处理大型数据集
setBounds() {
return new Promise((resolve, reject) => {
const bounds = new mapboxgl.LngLatBounds();
let i = 0;
while (i < GEO_JSON.length) {
bounds.extend(GEO_JSON[i].geometry.coordinates/OR/Markers_ARRAY);
i++;
}
if (bounds) {
resolve(bounds);
} else {
reject(`error:${ bounds}`);
}
});
},
fitBoundsToMarkers() {
this.setBounds().then((bounds) => {
map.fitBounds(bounds, {
padding: {
top: 100,
bottom: 100,
left: 100,
right: 100,
},
maxZoom: 14,
});
});
},
我正在使用 Mapbox GL JS v0.14.2,并且我通过文档进行了高低搜索,对此知之甚少。
如果您使用标准 JS API,使用他们提供的示例 (https://www.mapbox.com/mapbox.js/example/v1.0.0/fit-map-to-markers/); however the setup when using the GL api is quite different. The GL API has getBounds()
(https://www.mapbox.com/mapbox-gl-js/api/#Map.getBounds) 'fit map to markers' 就很清楚了,但是因为您没有命名层,就像标准的 JS API,所以我正在努力研究如何使用 getBounds()
。
我找到了这个 (
这是我的大部分设置;不包括 JSON 设置和其他选项。
mapboxgl.accessToken = '<myaccesstoken>';
var markers = <?php echo $programme_json; ?>;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/richgc/cikyo5bse00nqb0lxebkfn2bm',
center: [-1.470085, 53.381129],
zoom: 15
});
map.on('style.load', function() {
map.addSource('markers', {
'type': 'geojson',
'data': markers
});
map.addLayer({
"id": "markers",
"interactive": true,
"type": "symbol",
"source": "markers",
"layout": {
"icon-image": "venue-map-icon-blue",
'icon-size': 0.5,
"icon-allow-overlap": true
}
});
map.scrollZoom.disable();
});
我试过以下方法:
alert(map.getBounds()); // LngLatBounds(LngLat(-1.4855345239256508, 53.37642500812015), LngLat(-1.4546354760740883, 53.38583247227842))
var bounds = [[-1.4855345239256508, 53.37642500812015],[-1.4546354760740883, 53.38583247227842]]
map.fitBounds(bounds);
所以我知道如何 fitBounds,但我不确定如何获得它们 map.getBounds()
似乎 return 设置的中心位置 lng/lat。
标记 JSON:
var markers = {"type":"FeatureCollection","features":[{"type":"Feature","properties":{"title":"Site Gallery","url":"\/Freelance\/art-sheffield-2016\/programme\/site-gallery\/","summary":"Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Donec id justo. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Suspendisse feugiat. Etiam rhoncus.","image":"\/Freelance\/art-sheffield-2016\/site\/assets\/files\/1032\/site_gallery.jpg","marker-symbol":"venue-map-icon-blue","colour":"blue"},"geometry":{"type":"Point","coordinates":["-1.466439","53.376842"]}},{"type":"Feature","properties":{"title":"Moore Street Substation","url":"\/Freelance\/art-sheffield-2016\/programme\/moore-street-substation\/","summary":"","image":null,"marker-symbol":"venue-map-icon-green","colour":"green"},"geometry":{"type":"Point","coordinates":["-1.477881","53.374798"]}},{"type":"Feature","properties":{"title":"S1 Artspace","url":"\/Freelance\/art-sheffield-2016\/programme\/s1-artspace\/","summary":"","image":null,"marker-symbol":"venue-map-icon-red","colour":"red"},"geometry":{"type":"Point","coordinates":["-1.459620","53.380562"]}}]};
Mapbox 自己的 geojson-extent plugin will do the trick. Assuming your markers
object is valid GeoJSON,你可以简单地将它传递给 geojsonExtent()
函数来获得一组边界,然后你可以传递给 fitBounds()
.
加载 geojson-extent.js 文件后(例如,通过在 HTML 代码中使用 <script>
标记),您应该能够执行此操作以使您的地图适合GeoJSON markers
对象的边界:
map.fitBounds(geojsonExtent(markers));
更新
GeoJSONLint 报告您的 markers
对象不是有效的 GeoJSON,因为每个位置的元素都被解释为字符串,而不是数字。如果你从 lon-lat 坐标中删除引号,它应该可以正常工作:
var markers = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "Site Gallery",
"url": "\/Freelance\/art-sheffield-2016\/programme\/site-gallery\/",
"summary": "Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Donec id justo. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Suspendisse feugiat. Etiam rhoncus.",
"image": "\/Freelance\/art-sheffield-2016\/site\/assets\/files\/1032\/site_gallery.jpg",
"marker-symbol": "venue-map-icon-blue",
"colour": "blue"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.466439,
53.376842
]
}
},
{
"type": "Feature",
"properties": {
"title": "Moore Street Substation",
"url": "\/Freelance\/art-sheffield-2016\/programme\/moore-street-substation\/",
"summary": "",
"image": null,
"marker-symbol": "venue-map-icon-green",
"colour": "green"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.477881,
53.374798
]
}
},
{
"type": "Feature",
"properties": {
"title": "S1 Artspace",
"url": "\/Freelance\/art-sheffield-2016\/programme\/s1-artspace\/",
"summary": "",
"image": null,
"marker-symbol": "venue-map-icon-red",
"colour": "red"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.459620,
53.380562
]
}
}
]
};
如果您想使地图适合标记,您可以创建包含所有标记的边界。
var bounds = new mapboxgl.LngLatBounds();
markers.features.forEach(function(feature) {
bounds.extend(feature.geometry.coordinates);
});
map.fitBounds(bounds);
对于适用于所有 GeoJSON 对象的解决方案,而不仅仅是一组标记,请查看 Mapbox 的 Turf.js。
这段代码对我很有帮助:https://bl.ocks.org/danswick/83a8ddff7fb9193176a975a02a896792
但只是重复基础知识以防 link 死亡:
var bounds = turf.bbox(markers);
map.fitBounds(bounds, {padding: 20});
linked 代码中提到的 extent
方法已被弃用,取而代之的是 bbox
,但结果是一样的。
这是我基于 Mapbox example.
的 reduce 操作的解决方案它适用于包含点特征和多点特征(如线)的 geojson。
let bounds = geoJSON.features.reduce(function(bounds, feature) {
if(!Array.isArray(feature.geometry.coordinates[0])) { // point feature
return bounds.extend(feature.geometry.coordinates);
} else {
return feature.geometry.coordinates.reduce(function(bounds, coord) {
return bounds.extend(coord);
}, bounds);
}
}, new mapboxgl.LngLatBounds());
map.fitBounds(bounds, {
maxZoom: 12,
padding: 30, // in px, to make markers on the top edge visible
})
如果这里有人在使用 React-Map-GL,有两个以上的标记,并且想计算 before 的边界加载地图并检索 Mapbox 实例,您可以这样做:
const lat = myCoordinatesArray.map(location => parseFloat(location.lat));
const lng = myCoordinatesArray.map(location => parseFloat(location.lng));
// Note that WebMercatorViewport requires this format [lng, lat]
const minCoords = [Math.min.apply(null, lng), Math.min.apply(null, lat)];
const maxCoords = [Math.max.apply(null, lng), Math.max.apply(null, lat)];
const formattedGeoData = [minCoords, maxCoords];
const vPort = new WebMercatorViewport(this.state.viewport).fitBounds(formattedGeoData, {
padding: 100
});
const { latitude, longitude, zoom } = vPort;
来源:
您可以在渲染函数之前以构造函数的方式完成所有这些,并为插件初始化获取您的值。
改进的解决方案(基于@timur 解决方案)通过使用 while 循环和 promise
来处理大型数据集setBounds() {
return new Promise((resolve, reject) => {
const bounds = new mapboxgl.LngLatBounds();
let i = 0;
while (i < GEO_JSON.length) {
bounds.extend(GEO_JSON[i].geometry.coordinates/OR/Markers_ARRAY);
i++;
}
if (bounds) {
resolve(bounds);
} else {
reject(`error:${ bounds}`);
}
});
},
fitBoundsToMarkers() {
this.setBounds().then((bounds) => {
map.fitBounds(bounds, {
padding: {
top: 100,
bottom: 100,
left: 100,
right: 100,
},
maxZoom: 14,
});
});
},