在react-leaflet中将地图适配到要素层边界

3

我想要实现的目标:

有一个 <Map><FeatureGroup><Circle />[1 或 多个]...</FeatureGroup></Map> 的层次结构,使地图边界适合特征组,以便所有圆形都在视口中。

如果只有一个圆,则应该将边界适合(即:放大)到该圆上。

我尝试过的方法:

  1. FeatureGroup 一个 ref 并在上面调用 getBounds 以传递到 Map。由于生命周期的关系,当调用 componentDidMount 时,FeatureGroup 不存在 - 它稍后被渲染 (https://github.com/PaulLeCam/react-leaflet/issues/106#issuecomment-161594328)。
  2. Circle 存储在状态中并在其上调用 getBounds(在这种情况下假设只有一个圆)。那也行不通。

我认为我可能需要使用 React 上下文来解决这个问题,但我现在不能完全理解它,所以我需要一些帮助。

其他信息

我使用的是 react-leaflet@2.1.2

感谢提供任何帮助!

2个回答

2
由于在componentDidMount时无法获取Map的内容(https://github.com/PaulLeCam/react-leaflet/issues/106#issuecomment-161594328),因此您无法在该点上获取FeatureGroup的边界,并且在您分配的所有refs中,只有Map引用将在this.refs中可用。
但是,根据此GitHub评论,您可以为FeatureGroup提供一个onAdd处理程序函数:
<FeatureGroup ref="features" onAdd={this.onFeatureGroupAdd}>...

然后您可以使用 Map 引用来访问 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
    center={center}
    ref='map'
    zoom={zoom}
    maxZoom={18}
    onZoomEnd={this.onChangeView}
    onDragEnd={this.onChangeView}
  >
  ....
  </Map>

请记得给任何MarkerClusterGroup分组设置onClusterClick回调函数:

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

我发现我必须使用 onadd 而不是 onAdd<FeatureGroup onadd={onFeatureGroupAdd}> - notclive

1

你尝试过在componentWillMount函数中使用getBounds吗?如果不行,我建议你扩展FeatureGroup组件并添加一个onLoaded函数作为prop,在你扩展的组件的componentDidMount函数中调用该函数。通过扩展FeatureGroup组件,实际上是从这里复制/粘贴它。(如果你想知道为什么需要复制整个文件,请查看这个线程)

这还没有经过测试,但你的代码可能会像这样:

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,那么实际上这将更加容易,如果需要,我可以使用该代码编辑此答案。

啊,原来我是在componentDidMount里面做的。显然有人通过refs访问了Circle而不需要扩展任何组件(https://github.com/PaulLeCam/react-leaflet/issues/34),我也不愿意这样做,因为我不确定维护方面会有什么影响,但我想不出如何做到。我正在使用v2.1.2。如果我想不出其他办法,那我就试一下这个方法,但是似乎不需要这样做就可以实现。 - ndtreviv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接