10

我正在设置这样的 Mapbox GL JS 地图:

mapboxgl.accessToken = 'pk.my_token';
var cityBoundaries   = new mapboxgl.GeoJSONSource({ data: 'http://domain.com/city_name.geojson' } );
var map              = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v8',
  center: [cityLongitude,cityLatitude],
  zoom: 13
});

然后我将 GeoJSON 数据加载到地图上,如下所示:

map.on('style.load', function(){
  map.addSource('city', cityBoundaries);
  map.addLayer({
    'id': 'city',
    'type': 'line',
    'source': 'city',
    'paint': {
      'line-color': 'blue',
      'line-width': 3
    }
  });
});

此时,我有一张以我在 中指定的位置为中心的地图,new mapboxgl.Map它的缩放级别为 13。因此,只有一部分 GeoJSON 数据在地图上可见。我想重新居中并重新缩放地图,以便整个 GeoJSON 数据可见。

在 Mapbox JS 中,我会通过将 GeoJSON 数据加载到 afeatureLayer然后将地图拟合到其边界来做到这一点:

map.fitBounds(featureLayer.getBounds());

Mapbox GL JS的fitBounds 文档[[minLng, minLat], [maxLng, maxLat]]表明它需要.

有没有办法确定这个 GeoJSON 层的混合/最大纬度和经度值?

4

4 回答 4

8

根据这篇文章的“获取边界框”部分,我想出了这个过程......

map.on('style.load', function(){
  $.getJSON('http://citystrides.dev/city_name.geojson', function(response){
    var boundingBox = getBoundingBox(response);
    var cityBoundary = new mapboxgl.GeoJSONSource({ data: response } );

    map.addSource('city', cityBoundary);
    map.addLayer({
      'id': 'city',
      'type': 'line',
      'source': 'city',
      'paint': {
        'line-color': 'blue',
        'line-width': 3
      }
    });
    map.fitBounds([[boundingBox.xMin, boundingBox.yMin], [boundingBox.xMax, boundingBox.yMax]]);
  })
});

function getBoundingBox(data) {
  var bounds = {}, coords, point, latitude, longitude;

  for (var i = 0; i < data.features.length; i++) {
    coords = data.features[i].geometry.coordinates;

    for (var j = 0; j < coords.length; j++) {
      longitude = coords[j][0];
      latitude = coords[j][1];
      bounds.xMin = bounds.xMin < longitude ? bounds.xMin : longitude;
      bounds.xMax = bounds.xMax > longitude ? bounds.xMax : longitude;
      bounds.yMin = bounds.yMin < latitude ? bounds.yMin : latitude;
      bounds.yMax = bounds.yMax > latitude ? bounds.yMax : latitude;
    }
  }

  return bounds;
}

对于需要详细解释的任何人,以下是代码正在执行的操作的演练:

  • map.on('style.load', function(){
    • 当地图加载时,让我们在这个函数中做一些事情。
  • $.getJSON('http://citystrides.dev/city_name.geojson', function(response){
    • 获取城市的 GeoJSON 数据。这是一个异步调用,因此我们必须将所有使用此数据的代码(the response)放入此函数中。
  • var boundingBox = getBoundingBox(response);
    • 获取此 GeoJSON 数据的边界框。这是调用, function(){出现在“样式加载地图”块之后的 。
  • var cityBoundary = new mapboxgl.GeoJSONSource({ data: response } );
    • 构建 Mapbox 的 GeoJSON 数据。
  • map.addSource('city', cityBoundary);
    • 将源添加到 Mapbox。
  • map.addLayer({
    • 将图层添加到 Mapbox。
  • map.fitBounds([[boundingBox.xMin, boundingBox.yMin], [boundingBox.xMax, boundingBox.yMax]]);
    • 调整地图以将 GeoJSON 数据固定到视图中。
  • function getBoundingBox(data) {
    • 此函数遍历返回的 GeoJSON 数据,查找最小和最大纬度和经度值。

函数中需要注意的一件事getBoundingBox是这一行:

coords = data.features[i].geometry.coordinates;

在上面链接的原始帖子中,这一行的写法是coords = data.features[i].geometry.coordinates[0];因为它们的坐标列表数据是一个数组数组。我的数据不是这样格式化的,所以我不得不删除[0]. 如果您尝试此代码并且它爆炸了,那可能就是原因。

于 2016-02-28T17:07:22.253 回答
2

你可以使用turf.js图书馆。它有一个bbox功能:

const bbox = turf.bbox(foo);

https://turfjs.org/docs/#bbox

于 2019-08-07T10:01:20.147 回答
2

我使用了 turf-extent 库,它由 Mapbox 团队维护。https://www.npmjs.com/package/turf-extent是节点模块链接。在您的代码中,您只需 import(ES6) 或要求这样:

ES6/Webpack: import extent from 'turf-extent';
Via script tag: `<script src='https://api.mapbox.com/mapbox.js/plugins/turf/v2.0.2/turf.min.js'></script>`

然后将您的响应提供给该函数,例如:

ES6/Webpack: let orgBbox = extent(response);
Normal: var orgBbox = turf.extent(geojson);

然后你可以使用数组值来设置你的地图中心:

center: [orgBbox[0], orgBbox[1]]

或者如你所愿,以适应界限:

map.fitBounds(orgBbox, {padding: 20});

这是一个在常规 html 标记中使用 turf.min.js 的示例,以防您不使用 webpack 或浏览器: https ://bl.ocks.org/danswick/83a8ddff7fb9193176a975a02a896792

快乐的编码和映射!

于 2016-11-25T17:21:16.960 回答
2

基于詹姆斯骑士的回答。对于在 Mapbox Studio 中分配给地图的多边形/多多边形图块集,我使用它来获取边界框:

getPolygonBoundingBox: function(feature) {
    // bounds [xMin, yMin][xMax, yMax]
    var bounds = [[], []];
    var polygon;
    var latitude;
    var longitude;

    for (var i = 0; i < feature.geometry.coordinates.length; i++) {
        if (feature.geometry.coordinates.length === 1) {
            // Polygon coordinates[0][nodes]
            polygon = feature.geometry.coordinates[0];
        } else {
            // Polygon coordinates[poly][0][nodes]
            polygon = feature.geometry.coordinates[i][0];
        }

        for (var j = 0; j < polygon.length; j++) {
            longitude = polygon[j][0];
            latitude = polygon[j][1];

            bounds[0][0] = bounds[0][0] < longitude ? bounds[0][0] : longitude;
            bounds[1][0] = bounds[1][0] > longitude ? bounds[1][0] : longitude;
            bounds[0][1] = bounds[0][1] < latitude ? bounds[0][1] : latitude;
            bounds[1][1] = bounds[1][1] > latitude ? bounds[1][1] : latitude;
        }
    }

    return bounds;
}
于 2017-03-17T13:51:47.243 回答