最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Conditionally allow addition of markers in OpenLayer - Stack Overflow

programmeradmin1浏览0评论

I have a React (Vite) app in which I want to conditionally allow users to add markers when they click on the map.

I have the following logic

a useMap hook which does pretty much all the logic of rendering of the map and clicking on existing markers

import { Map } from "ol";
import { Vector as LayerVector } from "ol/layer";
import { Vector as SourceVector } from "ol/source";
import { defaults, ScaleLine } from "ol/control";
import proj4 from "proj4";
import { register } from "ol/proj/proj4";

import { useEffect, useMemo, useRef } from "react";

import { redMarker } from "../styles/markerStyles";
import { initMap } from "../utils/initMap";
import { MarkerDetails, onMarkerClick } from "../utils/onMarkerClick";
import { addMarker } from "../utils/addMarker";

const useMap = (
  setMap: React.Dispatch<React.SetStateAction<Map | null>>,
  setMarkerDetails: React.Dispatch<React.SetStateAction<MarkerDetails | null>>,
  isEditEnabled: boolean
): void => {
  proj4.defs(
    "EPSG:2056",
    "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs"
  );
  register(proj4);

  const { iconFeature, backgroundLayer, view } = initMap();

  //set style from an array fetched from api
  iconFeature.setStyle(redMarker);

  const mapRef = useRef<Map | null>(null);
  // const vectorSource = useMemo(() => {
  //   return new SourceVector({
  //     features: [iconFeature],
  //   });
  // }, [iconFeature]);

  // const markerLayer = useMemo(() => {
  //   return new LayerVector({
  //     source: vectorSource,
  //   });
  // }, [vectorSource]);

  useEffect(() => {
    const vectorSource = new SourceVector({
      features: [iconFeature],
    });

    const markerLayer = new LayerVector({
      source: vectorSource,
    });

    if (!mapRef.current) {
      mapRef.current = new Map({
        target: "map",
        controls: defaults().extend([
          new ScaleLine({
            units: "metric",
          }),
        ]),
        layers: [backgroundLayer, markerLayer],
        view: view,
      });
      setMap(mapRef.current);
    }

    mapRef.current.setTarget("map");

    //TODO: FIX THIS now working with edit mode
    // if (isEditEnabled) addMarker(mapRef.current, vectorSource);

    onMarkerClick(mapRef.current, iconFeature, setMarkerDetails);

    return () => mapRef.current?.setTarget(undefined);
  }, [
    backgroundLayer,
    iconFeature,
    isEditEnabled,
    setMap,
    setMarkerDetails,
    view,
  ]);
};

export default useMap;

addMarker.ts function

import { Feature, Map } from "ol";
import { Point } from "ol/geom";
import { Vector as SourceVector } from "ol/source";
import { redMarker } from "../styles/markerStyles";

export const addMarker = (map: Map, vectorSource: SourceVector): void => {
  map.on("click", function (evt) {
    //add marker on click
    const location = evt.coordinate;

    console.log("cal");

    const x = location[0];
    const y = location[1];

    const createdMarker = new Feature({
      geometry: new Point([x, y]),
      name: "add a meaningful name",
    });

    createdMarker.setStyle(redMarker);
    vectorSource.addFeature(createdMarker);

    vectorSource.changed();
  });
};

the isEditingEnabled flag comes from a setState defined in a Map component and on a click of a button I toggle this on/off

For some reason, even if the flag is ON, the marker never gets added. If I don't use the flags and I allow the user to be able to add marker at any point, it works.

I am using Open Layer 6. Any suggestions?

Also, will it hurt if I have another function that listens to the same click event but for when you click an existing marker.

import { Feature, Map } from "ol";

export type MarkerDetails = {
  title?: string;
  description?: string;
};

export const onMarkerClick = (
  map: Map,
  iconFeature: Feature,
  setMarkerDetails: React.Dispatch<React.SetStateAction<MarkerDetails | null>>
): void => {
  map.on("click", function (evt) {
    const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
      return feature;
    });

    if (feature === iconFeature) {
      //get values of object - open popup
      const selectedMarker = iconFeature.getProperties() as MarkerDetails;

      setMarkerDetails(selectedMarker);
    }
    if (!feature) {
      setMarkerDetails(null);
    }
  });
};

Thank you

发布评论

评论列表(0)

  1. 暂无评论