【问题标题】:How do you call fitBounds() when using leaflet-react?使用 Leaflet-react 时如何调用 fitBounds()?
【发布时间】:2018-11-24 11:55:26
【问题描述】:

我不知道如何在 Leaflet 地图上调用 fitBounds()。

如果我只是使用香草传单,此解决方案将完美运行:Zoom to fit all markers in Mapbox or Leaflet

不幸的是,我正在使用 react-leaflet。

如果我只是单独使用传单,这就是解决方案。

var leafletMap = new L.featureGroup([marker1, marker2, marker3]);
map.fitBounds(leafletMap.getBounds());

我认为这段代码(我的代码)this.mapRef.current.leafletElement 等价于var leafletMap = new L.featureGroup([marker1, marker2, marker3]); leafletMap.getBounds();,但是在 react-leaflet 中map.fitBounds(); 等价于什么?

基本上,我试图在地图上显示多个标记并相应地调整视图(放大、缩小、飞到等)。

这是我的代码。

import React, { createRef, Component } from 'react'
import { Map, TileLayer, Marker, Popup, FeatureGroup } from 'react-leaflet'

export default class MasterLeafletMap extends Component {
  constructor(props) {
    super(props);
    this.markers = this.markers.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.mapRef = createRef()
  }

  handleClick() {
    const leafletMap = this.mapRef.current.leafletElement;
    this.mapRef.current.fitBounds(leafletMap.getBounds()); // Doesn't work
    leafletMap.fitBounds(leafletMap.getBounds()); // Doesn't work (just trying to get the bounds of the markers that are there and adjust the view)
    this.mapRef.current.leafletElement.flyToBounds(leafletMap.getBounds()); // Doesn't work
  }
  markers() {
    if (this.props.search.items instanceof Array) {
      return this.props.search.items.map(function(object, i) {
        const position = [object._geoloc.lat, object._geoloc.lng];
        return <Marker position={position}>
          <Popup>
            <span>
              <h4>{object.title}</h4>
              {object.address}, <br /> {object.city}, {object.state}, {object.zip} <br /> {object._geoloc.lat}, {object._geoloc.lng}
            </span>
          </Popup>
        </Marker>
      })
    }

  }
  render() {
    const hasLoaded = this.props.search.items instanceof Array;
    if (!hasLoaded) {
      return null;
    }

    const position = [this.props.search.items[0]._geoloc.lat, this.props.search.items[0]._geoloc.lng];

    return (
      <div className="leaflet-map-container">
        <div onClick={this.handleClick}>Hello</div>
        <Map center={position} zoom={13} ref={this.mapRef}>
          <TileLayer
            attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          />
          <FeatureGroup>
            {this.markers()}
          </FeatureGroup>
        </Map>
      </div>
    )
  }
}

提前致谢。

【问题讨论】:

  • 我试图理解你的例子。当您调用map.fitBounds() 时,您应该提供您希望地图适合的边界。由于您尝试在当前边界上 fitBounds 我猜什么都不会发生?您可以尝试在标记数组的所有 LatLng 值上拟合边界吗? (我认为标记数组 === this.props.search.items?

标签: javascript reactjs leaflet react-leaflet fitbounds


【解决方案1】:

这是一个如何通过react-leaflet完成它的示例

handleClick() {
    const map = this.mapRef.current.leafletElement;  //get native Map instance
    const group = this.groupRef.current.leafletElement; //get native featureGroup instance
    map.fitBounds(group.getBounds());
}

在哪里

<div>
    <button onClick={this.handleClick}>Zoom</button>
    <Map
      center={this.props.center}
      zoom={this.props.zoom}
      ref={this.mapRef}
    >
      <TileLayer
        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <FeatureGroup ref={this.groupRef}>
        {this.props.locations.map(location => (
          <Marker
            key={location.name}
            position={{ lat: location.lat, lng: location.lng }}
          >
            <Popup>
              <span>
                <h4>{location.name}</h4>
              </span>
            </Popup>
          </Marker>
        ))}
      </FeatureGroup>
    </Map>
 </div>

对应于

var leafletMap = new L.featureGroup([marker1, marker2, marker3]);
map.fitBounds(leafletMap.getBounds());

Here is a demo

【讨论】:

  • 感谢瓦迪姆!你的回答就是我要找的! Спасибо! :)
  • 有什么办法不使用ref
  • 您可以将this.mapRef.current.leafletElement 替换为useMap() 以将其中一个引用替换为钩子。这有点干净:react-leaflet.js.org/docs/api-map/#usemap。我也在使用 React 钩子,发现 getBounds 定义在 current 而不是 leafletElement 这样 map.fitBounds(groupRef.current.getBounds()) 工作。
【解决方案2】:

如果您希望在地图加载时出现这种行为,您可以使用onlayeradd 事件。

例子:

const fitToCustomLayer = () => {
    if (mapRef.current && customAreaRef.current) { //we will get inside just once when loading
        const map = mapRef.current.leafletElement
        const layer = customAreaRef.current.leafletElement
        map.fitBounds(layer.getBounds().pad(0.5))
    }
}

return (
<Map ref={mapRef} onlayeradd={fitToCustomLayer}>
    <LayersControl position="topright">
        <Overlay checked key="customArea" name="Área de interesse">
            <GeoJSON ref={customAreaRef} data={collection} style={geoJSONStyle} />
        </Overlay>
        <BaseLayer name="Open Street Map">
            <TileLayer attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' 
 url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
        </BaseLayer>            
    </LayersControl>
</Map>
)

*编辑:如果参考层是最后一层,这似乎不起作用。将它放在基础层之前不会影响渲染并且可以工作。

如果您出于正当目的需要使用onlayeradd,请确保添加另一个标志以避免进入if 并再次触发fitBounds 并丢失地图的当前位置。

Ps:我尝试了react-leaflet的onload方法,但是it doesn't seems to work

【讨论】:

  • 这样fitBounds可以被多次调用。 onlayeradd 被所有层调用,因此对于GeoJSON 之后的每一层,这些引用存在。一种可能的解决方法是将GeoJSON ref 替换为useCallback hook
猜你喜欢
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多