отображать открытые слои информационного окна в React - PullRequest
0 голосов
/ 25 марта 2020

Я пытаюсь отобразить информационное окно (всплывающее окно наложения), когда пользователь нажимает на один из маркеров, отображаемых на карте. Вот код:

export const Home = () => {
  const { centerPoint, zoomValue, testSites } = useContext(AppContext);
  const [layer, setLayer] = useState<VectorLayer>(new VectorLayer({}));
  const [popup, setPopup] = useState<Overlay>(new Overlay({}));
  const popupRef = useRef<HTMLDivElement>(null);
  const contentRef = useRef<HTMLDivElement>(null);
  const [map] = useState(
    new Map({
      interactions: defaultInteractions().extend([
        new DragRotateAndZoom()
      ]),
      controls: defaultControls().extend([
        new ScaleLine({
          units: 'imperial'
        })
      ]),
      target: '',
      layers: [new TileLayer({
        source: new SourceOSM()
      })],
      view: new View({
        center: fromLonLat([centerPoint.longitude, centerPoint.latitude]),
        zoom: zoomValue
      })
    })
  );

  useEffect(() => {
    map.setTarget('map');
    map.on('click', (event) => {
      const feature = map.forEachFeatureAtPixel(event.pixel, (feature) => {
        return feature;
      });

      if (feature) {
        popup.setPosition(event.coordinate);
        if (contentRef.current) {
          contentRef.current.innerHTML = '<p>' + feature.getProperties().name + '</p>';
        }
      }
    });
    map.on('pointermove', (event) => {
      if (!event.dragging) {
        map.getTargetElement().style.cursor = map.hasFeatureAtPixel(map.getEventPixel(event.originalEvent)) ? 'pointer' : '';
      }
    });

    setPopup(new Overlay({
      element: popupRef.current,
      positioning: 'bottom-center' as OverlayPositioning,
      stopEvent: false,
      offset: [9, 9],
    }));
  }, [map]);

  useEffect(() => {
    map.addOverlay(popup);
  }, [popup, map]);

  useEffect(() => {
    if (testSites.length) {
      const features: Feature[] = [];
      testSites.forEach((testSite: TestSite) => {
        const feature = new Feature({
          geometry: new Point(fromLonLat([testSite.longitude, testSite.latitude])),
          name: testSite.name,
          address: testSite.address,
          city: testSite.city,
          state: testSite.state,
          notes: testSite.notes
        });

        feature.setStyle(new Style({
          image: new Icon({
            src: 'images/site.png'
          })
        }));
        features.push(feature);
      });
      setLayer(new VectorLayer({
        source: new VectorSource({
          features: features
        })
      }));
      if (layer.getProperties().source !== null) {
        map.addLayer(layer);
      }
    }
    map.getView().animate({zoom: zoomValue}, {center: fromLonLat([centerPoint.longitude, centerPoint.latitude])}, {duration: 1000});
  }, [centerPoint, zoomValue, map, testSites]);

  return (
    <div className="map-wrapper">
      <div id="map"></div>
      <div id="popup" className="map-popup" ref={popupRef}>
        <div id="popup-content" ref={contentRef}></div>
      </div>
    </div>
  );
};

Практически все работает нормально, за исключением отображения информационного окна при нажатии на значок функции. Из того, что я могу сказать, позиционирование при нажатии применяется к другому div, а не к тому, который содержит. Смотрите скриншот ниже. Любая помощь будет оценена. Спасибо. enter image description here

1 Ответ

0 голосов
/ 25 марта 2020

Хорошо, я решил это. Я назначил идентификатор своему наложению, а затем сослался на него в функции события при нажатии.

setPopup(new Overlay({
  id: 'info',
  element: popupRef.current,
  positioning: 'bottom-center' as OverlayPositioning,
  stopEvent: false,
  offset: [9, 9],
}));

......

if (feature) {
  map.getOverlayById('info').setPosition(event.coordinate);
  if (contentRef.current) {
    contentRef.current.innerHTML = '<p>' + feature.getProperties().name + '</p>';
  }
}
...