【问题标题】:Turf.js to find bounding box of data loaded with Mapbox GL JS?Turf.js 找到用 Mapbox GL JS 加载的数据边界框?
【发布时间】:2018-08-27 11:48:06
【问题描述】:

我正在使用 Mapbox GL JS 从某些页面上的外部 URL 加载 GeoJSON。我想自动使地图适合我正在加载的多边形的边界。

我知道 turf.js's bbox method 可以帮助解决这个问题,但我不确定如何将 GeoJSON 放入 turf.bbox 调用中。

这是我现在的代码:

map.addSource('mylayer', {
    type: 'geojson',
    data: '/boundaries.geojson'
});
map.addLayer({
    "id": "mylayer",
    "type": "fill",
    "source": "mylayer",
    'paint': {
        'fill-color': '#088',
        'fill-opacity': 0.6
    }
});
var bbox = turf.bbox('mylayer');
map.fitBounds(bbox, {padding: 20});

但它失败了turf.min.js:1 Uncaught Error: Unknown Geometry Type。文档说bbox 想要“任何 GeoJSON 对象”。

如何正确执行此操作?我显然宁愿不加载外部文件两次。

【问题讨论】:

    标签: mapbox mapbox-gl-js turfjs


    【解决方案1】:
    1. 从远程源加载数据是异步的。也就是说,您正在尝试在加载数据之前对其进行分析。

    所以你需要处理sourcedata 事件。

    1. bbox函数的输入参数是一个有效的GeoJson object

    2. 如前所述,Turf.jsMapbox 一无所知,因此您还需要从源中读取加载的数据。

    3. 举个例子:

        map.addSource('mylayer', {
            type: 'geojson',
            data: '/boundaries.geojson'
        });
        map.addLayer({
            "id": "mylayer",
            "type": "fill",
            "source": "mylayer",
            'paint': {
                'fill-color': '#088',
                'fill-opacity': 0.6
            }
        });
    
        map.on('sourcedata', function (e) {
          if (e.sourceId !== 'mylayer' || !e.isSourceLoaded) return
          var f = map.querySourceFeatures('mylayer')
          if (f.length === 0) return
          var bbox = turf.bbox({
            type: 'FeatureCollection',
            features: f
          });
          map.fitBounds(bbox, {padding: 20});    
        })
    
    

    【讨论】:

    • 这对我有用,但请注意您的源名称和图层名称相同。在“源数据”事件监听器中,“mylayer”指的是源名称。
    【解决方案2】:

    不要将 URL 传递给 addSource,而是先下载它,然后传递完整的 GeoJSON 对象。

    $.getJSON('/boundaries.geojson', (geojson) => {
       map.addSource('mylayer', {
           type: 'geojson',
           data: geojson
       });
       map.fitBounds(turf.bbox(geojson), {padding: 20});
    }
    

    用任何其他请求库替换 jQuery。

    【讨论】:

      【解决方案3】:

      turf.bbox 函数接受 GeoJSON 作为对象,它不知道 Mapbox。

      当您通过传递完整的 GeoJSON(而不是传递 URL)创建源时,Mapbox GeoJSON 源将完整的 GeoJSON 对象私有存储在 ._data 中,因此您可以这样做:

      turf.bbox(map.getSource('mylayer')._data);
      

      但是,._data 可能会在任何新版本中随时更改,而无需在发行说明中详细说明,因为它是一个私有 API。

      有一个公共 API map.querySourceFeatures:

      map.querySourceFeatures('mylayer');
      

      但它只会返回当前视图中的特征,并且在被 geojson-vt 平铺后意味着即使在查看整个世界时也不能保证返回所有特征。

      【讨论】:

      • 谢谢!实际上,我的 GeoJSON 源似乎没有将完整的 GeoJSON 对象存储在 ._data - 我所拥有的是 URL,即 '/boundaries.geojson'
      • map.querySourceFeatures('ward') 返回[]
      • 你是对的,当你传递一个 URL 来创建源时,_data 将不起作用。您需要先自己下载 GeoJSON 并在创建新 Source 时传入完整的 Object,这样您就可以访问原始 GeoJSON 数据以获取草皮。 querySourceFeatures 将通过 geojson-vt 返回平铺数据,因此如果您缩小并决定删除该功能,因为它太小或超出视口,它将不会包含在结果中。
      猜你喜欢
      • 2016-03-20
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 2021-01-27
      • 2017-03-26
      • 2017-11-07
      • 2017-08-10
      • 2021-10-02
      相关资源
      最近更新 更多