将地图拟合到 react-leaflet 中的要素层边界

Fit map to feature layer bounds in react-leaflet

我想达到的目标:

具有 <Map><FeatureGroup><Circle />[1 or more]...</FeatureGroup></Map> 层次结构并使地图边界适合要素组,以便所有圆圈都在视口中。

如果只有一个圆圈,它应该适合该圆圈的边界(即:放大)。

我尝试过的:

  1. FeatureGroup 一个 ref 并在其上调用 getBounds 以传递给 Map。由于生命周期 FeatureGroup 在调用 componentDidMount 时不存在 - 它稍后呈现 (https://github.com/PaulLeCam/react-leaflet/issues/106#issuecomment-161594328)。
  2. 在状态中存储 Circle 并在其上调用 getBounds(假设,在这种情况下,只有一个圆圈。那也不起作用。

我想我可能需要对 React Context 做些什么,但我不确定我现在是否完全理解它,所以我需要一些帮助。

其他信息

我正在使用 react-leaflet@2.1.2

感谢您提供的任何帮助!

您是否尝试过在 componentDidMount 函数中执行 getBounds 而不是 componentWillMount?如果这不起作用,那么我建议扩展 FeatureGroup 组件并添加一个 onLoaded 函数作为 prop 并在扩展组件的 componentDidMount 函数中调用该函数。通过扩展 FeatureGroup 组件,我实际上是指 copying/pasting 来自 here. (if you care about why you need to copy that whole file check this 线程)

这没有经过测试,但您的代码可能类似于

import { FeatureGroup } from 'leaflet';

import { withLeaflet, Path } from 'react-leaflet';

class CustomFeatureGroup extends Path {
  createLeafletElement(prop) {
    const el = new FeatureGroup(this.getOptions(props));
    this.contextValue = {
      ...props.leaflet,
      layerContainer: el,
      popupContainer: el,
    };
    return el;
  }

  componentDidMount() {
    super.componentDidMount();
    this.setStyle(this.props);
    /*
     Here you can do your centering logic with an onLoad callback or just
     by using this.leafletElement.map or whatever
    */
    this.props.onLoaded();
  }
}

export default withLeaflet(CustomFeatureGroup)

注意:如果您使用的是 react-leaflet V1,这实际上更容易,如果需要,我可以使用该代码编辑此答案。

因为 Map 的内容在 componentDidMount-time (https://github.com/PaulLeCam/react-leaflet/issues/106#issuecomment-161594328) 时不可用,你无法在那个时候获得 FeatureGroup 的边界,并且出在您分配的所有 refs 中,只有 Map ref 将在 this.refs.

中可用

然而,根据这个 GitHub 评论:https://github.com/PaulLeCam/react-leaflet/issues/106#issuecomment-366263225 你可以给一个 FeatureGroup 一个 onAdd 处理函数:

<FeatureGroup ref="features" onAdd={this.onFeatureGroupAdd}>...

然后您可以使用 Map refs 访问 leafletElement 并使用传入事件目标的边界调用 fitBounds,这将是 FeatureGroup :

  onFeatureGroupAdd = (e) => {
    this.refs.map.leafletElement.fitBounds(e.target.getBounds());
  }

这将根据需要将地图“缩放”到您 FeatureGroup 的范围内。

更新

我修改了我的 React 组件,以便缩放和居中由查询参数控制。上述解决方案的问题是,如果您通过单击放大 MarkerClusterGroup,例如,它会更新 url 中的缩放,重新渲染地图并重新调用 onFeatureGroupAdd,从而消除所有标记簇的优点。

我需要的是访问将新绘制的圆很好地保持在边界内所需的缩放级别,然后使用正确的缩放级别和中心更新 url。

  onDrawCircle = (e) => {
    ...
    var targetZoom = this.refs.map.leafletElement.getBoundsZoom(e.layer.getBounds());
        // Call function to update url here:
        functionToUpdateUrl(targetZoom, e.layer.getBounds().getCenter());
    }
  }

为了能够控制整个地图,我还在 onZoomEndonDragEnd 事件处理程序中调用了 functionToUpdateUrl,如下所示:

  onChangeView = (e) => {
      functionToUpdateUrl(e.target._zoom, this.refs.map.leafletElement.getCenter());
  }

还有一个用于处理集群点击:

  onClusterClick = (e) => {
     // This time we want the center of the layer, not the map?
     functionToUpdateUrl(e.target._zoom, (e.layer ? e.layer.getBounds().getCenter() : e.target.getBounds().getCenter()));
  }

然后,在渲染 Map 元素时,传递这些属性:

  <Map
    center={center}
    ref='map'
    zoom={zoom}
    maxZoom={18}
    onZoomEnd={this.onChangeView}
    onDragEnd={this.onChangeView}
  >
  ....
  </Map>

并记得给任何MarkerClusterGroup他们的onClusterClick回调:

<MarkerClusterGroup onAdd={this.onMarkerGroupAdd} onClusterClick={this.onClusterClick}>