在地图外单击打开弹出窗口

Open Pop Up on Click Outside of Map

我有一个列表,通过单击列表元素,我想打开标记上的弹出窗口。目前,弹出窗口仅在单击标记时打开。

这就是我创建标记和弹出窗口的方式

import React from 'react';
import {
  CircleMarker,
  Popup,
} from 'react-leaflet';

class PointsLayer extends React.Component {
  render() {
    const { data } = this.props;
    return (
      data.map(point => {
        return (
          <CircleMarker
            key={point.id}
            center={point.coordinates}>
            <Popup>
              Fancy Pop Up
            </Popup>
          </CircleMarker>
        )
      })
    )
  }

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
  Map,
} from 'react-leaflet';
import L from 'leaflet';
import PointsList from './PointsList;
import PointsLayer from './PointsLayer;

class Map extends React.Component {

componentDidMount() {
    this.map = this.mapInstance.leafletElement;
}

render() {
  const { data } = this.props;
  return (
    <>
      <Map
        ref={e => { this.mapInstance = e }}}>
        <TileLayer
          url=..." />
        <PointsLayer
           data={data} />
       </Map>
       <PointsList
         data={data} />
     </>
   )
 }

}

来自 data 的每个数据点都是 <Map /><PointsLayer /> 组件上的一个标记,以及 <PointsList /> 中的一个侦听器。 单击 <PointsList /> 中的相应条目时,我想在 <PointsLayer /> 中打开弹出窗口。

我该怎么做?

您可以在对象(列表)上使用 onClick 侦听器,以便在单击列表元素时调用类似此函数的功能。

onItemClick: function (event) {
// open popup method 
    event.openPopup();

},

打开PopupMarker.openPopup() method可以使用。以下组件演示了如何访问 react-leaflet 库中的原生 Marker 对象并打开 Popup:

function MarkerExample(props) {
  const markerRef = useRef(null);
  const { center, content, openPopup } = props;

  useEffect(() => {
    markerRef.current.leafletElement.openPopup();
  }, []);

  return (
    <CircleMarker ref={markerRef} center={center}>
      <Popup>{content}</Popup>
    </CircleMarker>
  );
}

以下是您的示例的更改列表:

a) 为标记引入一个单独的组件,它接受一个 openPopup 属性来确定是否需要打开 Popup:

function PointMarker(props) {
  const markerRef = useRef(null);
  const { center, content, openPopup } = props;

  useEffect(() => {
    if (openPopup) markerRef.current.leafletElement.openPopup();
  }, [openPopup]);

  return (
    <CircleMarker ref={markerRef} center={center}>
      <Popup>{content}</Popup>
    </CircleMarker>
  );
}

b)修改PointsList组件以通过事件处理程序传输所选项目的索引,如下所示:

function PointsList(props) {
  const { data, onItemClick } = props;
  return (
    <div>
      <ul>
        {data.map((item, index) => (
          <li
            key={index}
            onClick={e => {
              onItemClick(index);
            }}
          >
            {item.name}
          </li>
        ))}
      </ul>
    </div>
  );
}

c) 最后在地图组件中引入 所选标记 的索引为 state variable。现在单击外部元素后,更新选定的索引以打开弹出窗口:

function MapExample(props) {
  const [selected, setSelected] = useState();
  const { zoom, center, locations } = props;

  function handleItemClick(index) {
    setSelected(index);
  }

  return (
    <div>
      <PointsList data={locations} onItemClick={handleItemClick} />
      <Map center={center} zoom={zoom}>
        <TileLayer url="https://{s}.tile.osm.org/{z}/{x}/{y}.png" />
        <PointsLayer selectedIndex={selected} data={locations}  />
      </Map>
    </div>
  );
}

Here is a demo