Leaflet中基于参考点实现图像旋转、缩放与平移匹配的问题
Leaflet图像叠加配准功能优化问题
我正在实现一个让用户将图像叠加到Leaflet地图的功能,流程是用户在图像和地图上各选择两个参考点(使用地图坐标),通过这四个点对图像进行旋转、缩放和平移,让图像匹配地图上的目标位置。目前旋转和缩放有初步效果但不理想,而且还没处理平移部分。相关代码如下:
const PlantEditDrawer = () => { const { isPlantEditDrawerOpen } = useDashBoardContext(); const [mounted, setMounted] = useState(false); const { leafletMap } = useLeafletMapContext(); const { north, east, south, west } = usePositionBoundsContext(); const [firstImage, setFirstImage] = useState<L.LatLng>(); const [secondImage, setSecondImage] = useState<L.LatLng>(); const [firstMap, setFirstMap] = useState<L.LatLng>(); const [secondMap, setSecondMap] = useState<L.LatLng>(); const [isDone, setDone] = useState(false); // const [imageBounds, setImageBounds] = useState<number[]>() const imageRef = useRef<L.ImageOverlay>(); useEffect(() => { if (mounted) return; setMounted(true); }, [mounted]); const handleSecondMapClick = useCallback( (e: LeafletMouseEvent) => { setSecondMap(e.latlng); leafletMap?.current!.off("click"); setDone(true); }, [leafletMap] ); const handleSecondImageClick = useCallback( (e: LeafletMouseEvent) => { setSecondImage(e.latlng); if (imageRef.current && leafletMap?.current) { leafletMap.current.removeLayer(imageRef.current); leafletMap.current.on("click", handleSecondMapClick); } }, [handleSecondMapClick, leafletMap] ); const handleFirstMapClick = useCallback( (e: LeafletMouseEvent) => { setFirstMap(e.latlng); imageRef.current?.addTo(leafletMap?.current!); imageRef.current?.on("click", handleSecondImageClick); leafletMap?.current!.off("click"); }, [handleSecondImageClick, leafletMap] ); const handleFirstImageClick = useCallback( (e: LeafletMouseEvent) => { setFirstImage(e.latlng); if (imageRef.current && leafletMap?.current) { imageRef.current.off("click"); leafletMap.current.removeLayer(imageRef.current); leafletMap.current.on("click", handleFirstMapClick); } }, [handleFirstMapClick, leafletMap] ); useEffect(() => { if (!leafletMap?.current) return; const bounds = L.latLngBounds([ [south, west], [north, east], ]); imageRef.current = L.imageOverlay(image, bounds, { interactive: true, opacity: 0.5, }).addTo(leafletMap.current); imageRef.current?.on("click", handleFirstImageClick); }, [east, leafletMap, north, south, west, mounted, handleFirstImageClick]); function calculateAngle(p1:any, p2:any) { const deltaX = p2.lng - p1.lng; const deltaY = p2.lat - p1.lat; return Math.atan2(deltaX, deltaY) * (180 / Math.PI); } useEffect(() => { if (!isDone || !firstImage || !secondImage || !firstMap || !secondMap) return; //计算角度 const mapAngle = calculateAngle(firstMap, secondMap) const imageAngle = calculateAngle(firstImage, secondImage) const rotationRequired = mapAngle - imageAngle; const firstImageLatLng = L.latLng(firstImage.lat, firstImage.lng); const secondImageLatLng = L.latLng(secondImage.lat, secondImage.lng); const imageDistance = firstImageLatLng.distanceTo(secondImageLatLng); const firstMapLatLng = L.latLng(firstMap.lat, firstMap.lng); const secondMapLatLng = L.latLng(secondMap.lat, secondMap.lng); const mapDistance = firstMapLatLng.distanceTo(secondMapLatLng); const scaleFactor = mapDistance / imageDistance; if (imageRef.current) { imageRef.current.addTo(leafletMap?.current!); const test = imageRef.current.getElement(); test!.style.transformOrigin = "center"; const { transform } = test!.style; test!.style.transform = `${transform} rotate(${rotationRequired}deg) scale(${scaleFactor})`; } }, [firstImage, firstMap, isDone, leafletMap, secondImage, secondMap]); // 未添加返回值 }
内容的提问来源于stack exchange,提问作者Malxruxes
相关产品推荐
相关产品推荐

