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

Sto*_*ace 5 javascript leaflet reactjs react-leaflet

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

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

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>
        )
      })
    )
  }
Run Code Online (Sandbox Code Playgroud)

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} />
     </>
   )
 }
Run Code Online (Sandbox Code Playgroud)

}

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

我该怎么做?

Vad*_*hev 7

可以使用打开弹出窗口的Marker.openPopup()方法。以下组件演示了如何访问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>
  );
}
Run Code Online (Sandbox Code Playgroud)

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

a) 为接受一个openPopupprop的标记引入一个单独的组件,以确定是否需要打开 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

c) 最后在地图组件中引入所选标记的索引作为状态变量。现在一旦外部元素被点击,更新选定的索引以打开弹出窗口:

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是一个演示