Mapbox GL JS:缩放到过滤后的多边形?

问题描述 投票:0回答:4

我正在使用 Mapbox GL JS 来显示多边形图层。我会允许用户从下拉列表中选择一个名称,然后突出显示并缩放到匹配的多边形。

我已经知道如何使用

map.setFilter
突出显示匹配多边形,但我不知道如何缩放到匹配多边形的边界。这是我当前的代码:

map.addLayer({
    'id': 'polygon_hover',
    'source': 'mysource',
    'source-layer': 'mylayer',
    'type': 'fill',
    'paint': {
        'fill-color': 'red',
        "fill-opacity": 0.6
    },
    "filter": ["==", 'CUSTNAME', ""]
});
// Get details from dropdown
custname.on("change", function(e) {
    // get details of name from select event
    map.setFilter('polygon_hover', ["==", 'CUSTNAME', name]);
    // Get bounds of filtered polygon somehow?
    // var bounds = ??;
    // map.fitBounds(bounds);
});

我已经检查了 Mapbox 缩放到边界的示例,但它假定您已经知道边界是什么。

有什么方法可以让多边形的边界与 Mapbox 中的地图过滤器匹配?

mapbox mapbox-gl-js
4个回答
5
投票

我有以下代码来将边界拟合到多边形中心坐标:

var coordinates = f.geometry.coordinates[0];
var bounds = coordinates.reduce(function (bounds, coord) {
    return bounds.extend(coord);
}, new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]));

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

其中 f 是一个特征。


3
投票

我找到了解决你问题的方法。 Leaflet 有一个 polygon 类,它采用多边形坐标数组,并有一个名为

getBounds()
的函数,该函数返回西南和东北边界。然而,Leaflet 并没有遵循LngLat 的约定,它的格式是LatLng。因此,您必须切换它。我从 Mapbox Show drawn drawn polygon area 中拿了一个例子,并添加了你正在寻找的东西。

var polygon = data.features[0].geometry.coordinates;
var fit = new L.Polygon(polygon).getBounds();
var southWest = new mapboxgl.LngLat(fit['_southWest']['lat'], fit['_southWest']['lng']);
var northEast = new mapboxgl.LngLat(fit['_northEast']['lat'], fit['_northEast']['lng']);
var center = new mapboxgl.LngLatBounds(southWest, northEast).getCenter();
// map.flyTo({center: center, zoom: 10});
map.fitBounds(new mapboxgl.LngLatBounds(southWest, northEast));

2
投票

我看到这个问题仍然相关 - 我解决了它,向包含给定多边形和建筑物边界的所有点的数据库发出单独请求

[[minLng, minLat], [maxLng, maxLat]]
。 所有解决已渲染几何或源特征的尝试对我都不起作用——很可能是因为 Mapbox 没有在图块中保留初始 geoJSON。


0
投票

这里有一个类似的问题和答案https://stackoverflow.com/a/35685551/10331580

我把那里的答案移植到自己的打字稿上。

getBoundingBox(feature: mapboxgl.MapboxGeoJSONFeature): mapboxgl.LngLatBoundsLike | undefined {
  let coordinates = (feature.geometry as any).coordinates[0];
  let bounds: {
    xMin?: number,
    xMax?: number,
    yMin?: number,
    yMax?: number
  } = {}

  for (let i = 0; i < coordinates.length; i++) {
    let longitude = coordinates[i][0];
    let latitude = coordinates[i][1];
    if (bounds.xMin && bounds.xMax && bounds.yMin && bounds.yMax) {
      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;
    } else {
      bounds.xMin = longitude
      bounds.xMax = longitude
      bounds.yMin = latitude
      bounds.yMax = latitude
    }
  }
  if (bounds.xMin && bounds.xMax && bounds.yMin && bounds.yMax) {
    return new mapboxgl.LngLatBounds(
      new mapboxgl.LngLat(bounds.xMin, bounds.yMin),
      new mapboxgl.LngLat(bounds.xMax, bounds.yMax)
    )
  }
  return undefined;
}

fitToPolygon(feature: mapboxgl.MapboxGeoJSONFeature) {
  let bounds = this.getBoundingBox(feature)
  if (bounds) {
    this.map.fitBounds(bounds, {
      padding: 20
    })
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.