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