Google 地图数据层问题

问题描述 投票:0回答:1

我目前在 Google Maps React API 和 Google Maps 文档方面遇到了很大的困难。我的目标是在地图上渲染多边形并进行各种操作。到目前为止,这就是我想到的。

我可以毫无问题地在地图上渲染从后端收到的 GeoJson。此外,我可以识别一个顶点,然后显示一个菜单以在该顶点上执行删除。效果很好。我的多边形立即更新。我在地图上看到了变化,当我记录我的多边形变量时,它也在那里。

问题出在我的 onSave 上。看起来,每次我的鼠标抬起时,它都会正确地触发像“hello”这样的 console.logs,但新的 geojson 结构的保存不会被传递。我已经测试过,回调是否有效,并且它确实有效,但它仅在第二次触发后更新多边形。

这就是我来这里寻求帮助的原因。也许有人可以在浏览我的代码时快速想到一个想法。由于我不是这方面的专家,因此我也会对整体处理进行一般性反馈。我觉得还可以改进。

export function MapComponents() {
  const t = useTranslations();
  const { fieldDataV2, setPolygon, polygon } = useFieldDetailsContext();
  const { map } = useLayoutProvider();
  const [text, setText] = useState('');
  const [counter, setCounter] = useState(0);
  const currentPolyCoordinates = polygon?.geometry?.coordinates;
  const currentFeature = map?.data.getFeatureById('test');

  const area =
    (currentPolyCoordinates && calculateArea(currentPolyCoordinates)) ||
    fieldDataV2?.boundary?.properties?.area;

  const setFeatureStyle = (
    feature: google.maps.Data.Feature,
  ): google.maps.Data.StyleOptions => {
    return {
      fillOpacity: feature.getProperty('fillOpacity') as number, // Set fill opacity
      fillColor: feature.getProperty('fillColor') as string, // Set fill color for the polygon
      strokeColor: feature.getProperty('color') as string, // Set stroke color based on the 'color' property
      strokeWeight: feature.getProperty('strokeWeight') as number,
      zIndex: feature.getProperty('zIndex') as number, // Set stroke weight as needed
      editable: true,
      clickable: true,
    };
  };

  const contentString = `<div
                            id="context-menu-delete-icon" style={{cursor: "pointer"}}
                          >Löschen</div`;

  const infowindow = new google.maps.InfoWindow({
    ariaLabel: 'Delete-Menu',
    content: contentString,
    disableAutoPan: true,
  });

  // This useEffect handles the initial drawing of the polygon on the map
  useEffect(() => {
    if (map) {
      // Add GeoJSON boundary data to the map
      fieldDataV2 && map.data.addGeoJson(fieldDataV2?.boundary);
      fieldDataV2 && setPolygon(fieldDataV2.boundary);
      // Set style for the added feature
      map.data.setStyle(setFeatureStyle);
    }

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [map, fieldDataV2]);

  const onEdit = (event: google.maps.PolyMouseEvent) => {
    const clickedPoint = event.latLng;
    const lngLatArray = clickedPoint && [
      clickedPoint.lng(),
      clickedPoint.lat(),
    ];

    // Check if the clicked point matches any polygon vertices and their lenght is greater then 3
    const isMatch =
      currentPolyCoordinates &&
      lngLatArray &&
      isPointInsideArrays(currentPolyCoordinates, lngLatArray);
    // Open the info window for deletion if there are enough points and we have a vertix match
    if (isMatch) {
      infowindow.open({ map });
      infowindow.setPosition(clickedPoint);
      infowindow.open({ map: map, shouldFocus: false });
      const coordinatesToWorkWith =
        lngLatArray &&
        currentPolyCoordinates &&
        removeFirstPointFromArray(lngLatArray, currentPolyCoordinates);
      // Remove the matched point and format the result for geometry modification
      const filteredAndConvertedCoordinates =
        coordinatesToWorkWith &&
        lngLatArray &&
        filterAndConvertCoordinates(coordinatesToWorkWith, lngLatArray);
      // Add a handler to the infowindow as soon as it gets domready
      google.maps.event.addListener(infowindow, 'domready', function () {
        const contextDeleteMenu = document.getElementById(
          'context-menu-delete-icon',
        );
        const infowindowDefaultCloseIcon =
          document.getElementsByClassName('gm-ui-hover-effect');
        if (infowindowDefaultCloseIcon instanceof HTMLCollection) {
          const infoWindowCloseX = infowindowDefaultCloseIcon[0] as HTMLElement;
          infoWindowCloseX.style.display = 'none';
        }
        if (contextDeleteMenu) {
          contextDeleteMenu.style.cursor = 'pointer';
          //Close the infowindow and set the new geometrie to the feature
          contextDeleteMenu.addEventListener('click', () => {
            infowindow.close();
            filteredAndConvertedCoordinates &&
              currentFeature?.setGeometry(
                new google.maps.Data.Polygon(filteredAndConvertedCoordinates),
              );
            currentFeature?.toGeoJson((data) => {
              setPolygon(data as GeoJsonFeaturePolygon);
              setText(JSON.stringify(data) + counter);
            });
          });
        }
      });
    }
  };

  const onSave = () => {
    currentFeature?.toGeoJson((data) => {
      setPolygon(data as GeoJsonFeaturePolygon);
      setText(JSON.stringify(data) + counter);
      setCounter(counter + 1);
    });
  };

  useEffect(() => {
    if (map) {
      // Close the info window anytime a user clicks anywhere on the map
      const mapClickHandler = google.maps.event.addListener(
        map,
        'click',
        () => {
          infowindow.close();
        },
      );

      // Handles click events on vertices
      const vertexClickHandler = map.data.addListener('click', onEdit);

      // Update the polygon to the state and remove the infowindow

      const saveGeometryHandler = map.data.addListener('mouseup', onSave);

      // Cleanup function removes all handlers to prevent multiple initiations on re-renders
      return () => {
        mapClickHandler.remove();
        vertexClickHandler.remove();
        saveGeometryHandler.remove();
      };
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [map, polygon]);
javascript reactjs typescript google-maps react-hooks
1个回答
0
投票

我找到了问题以及解决问题的方法。我的 onSave 调用应该从数据层对象中获取数据并将其传递给保存在状态中的多边形。问题是,当我做我的鼠标时,谷歌没有更新数据层,但之后。因此,我使用设置为 1 纳秒的去抖来实际获取更新的状态。一切正常。

© www.soinside.com 2019 - 2024. All rights reserved.