Подогнать карту к границам векторного слоя в реагирующей листовке

Чего я хочу достичь:

Имейте иерархию <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, но я не уверен, что полностью понимаю его прямо сейчас, поэтому мне нужна помощь.

Другая информация

Я использую [email protected]

Спасибо за любую предложенную помощь!


person ndtreviv    schedule 03.12.2018    source источник


Ответы (2)


Поскольку содержимое Map недоступно в componentDidMount времени (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());
    }
  }

Чтобы иметь возможность контролировать всю карту, я также вызываю functionToUpdateUrl в обработчиках событий onZoomEnd и onDragEnd, например:

  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>

И не забудьте дать всем MarkerClusterGroups их обратный вызов onClusterClick:

<MarkerClusterGroup onAdd={this.onMarkerGroupAdd} onClusterClick={this.onClusterClick}>
person ndtreviv    schedule 04.12.2018
comment
Я обнаружил, что должен использовать onadd, а не onAdd, <FeatureGroup onadd={onFeatureGroupAdd}>. - person notclive; 28.06.2020

Вы пытались сделать getBounds в функции componentDidMount вместо componentWillMount? Если это не сработает, я бы предложил расширить компонент FeatureGroup и добавить функцию onLoaded в качестве реквизита и вызвать эту функцию в функции 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, это на самом деле намного проще, и я могу отредактировать этот ответ с помощью этого кода, если это необходимо.

person jbccollins    schedule 03.12.2018
comment
А, оказывается, я делал это в componentDidMount. Очевидно, кому-то удалось получить доступ к Кругу через рефы без расширения каких-либо компонентов (github.com /PaulLeCam/react-leaflet/issues/34), что я тоже не хочу делать, так как не знаю, как это повлияет на техническое обслуживание, но я не могу понять, как это сделать. Я использую v2.1.2. Если я не могу понять что-нибудь еще, я попробую это, но кажется странным, что это невозможно без этого. - person ndtreviv; 04.12.2018