import React, { useEffect, useRef } from "react"; import StyleWrap from "./style"; import { useRecoilValue } from "recoil"; import { mapAtom, markerPositionAtom } from "@/store"; import Point from "@arcgis/core/geometry/Point"; import SpatialReference from "@arcgis/core/geometry/SpatialReference"; import { getDomOffset } from "@/utils"; interface Props { position?: LocationPoint; children: JSX.Element; align?: "center" | "right" | "left" | "bottom" | "bottomCenter"; pointHeight?: number; style?: CSSPerspective; className?: string[]; } export default function MarkerWrap(props: Props) { const { position, children, align = "center", style = {}, className = [] } = props; const view = useRecoilValue(mapAtom); const markerPosition = useRecoilValue(markerPositionAtom); const markerRef = useRef<HTMLDivElement>(null); const watrchHandle = useRef<IHandle>(); const pointToScreen = (location: LocationPoint) => { if (location && view) { const point = new Point({ x: location.x, y: location.y, spatialReference: view!.spatialReference }); const screen = view.toScreen(point); const mapWrap = view.container; const top = getDomOffset.top(mapWrap); const left = getDomOffset.left(mapWrap); console.log(top, left); if (markerRef.current) { const { clientWidth, clientHeight } = markerRef.current; if (align === "center") { markerRef.current.style.left = screen.x + left - clientWidth / 2 + "px"; markerRef.current.style.top = screen.y - clientHeight + top - 20 + "px"; } if (align === "right") { markerRef.current.style.left = screen.x + 20 + "px"; markerRef.current.style.top = screen.y - clientHeight / 2 + top + "px"; } if (align === "bottom") { markerRef.current.style.left = screen.x + left - clientWidth / 2 + "px"; markerRef.current.style.top = screen.y + clientHeight + "px"; } if (align === "bottomCenter") { markerRef.current.style.left = screen.x + left - clientWidth / 2 + "px"; markerRef.current.style.top = screen.y + clientHeight - 20 + "px"; } } } }; useEffect(() => { if (markerRef && markerRef.current && view) { if (position) { pointToScreen(position); watrchHandle.current = view.watch("extent", () => { pointToScreen(position); }); } else if (markerPosition) { pointToScreen(markerPosition); watrchHandle.current = view.watch("extent", () => { pointToScreen(markerPosition); }); } } }, [markerPosition, view, markerRef, position]); useEffect(() => { return () => { if (watrchHandle.current) watrchHandle.current.remove(); }; }, []); return ( (position || markerPosition) && ( <StyleWrap className={["MarkerWrap", ...className].join(" ")} id="markerpopup" ref={markerRef} style={style}> {children} </StyleWrap> ) ); } //获取元素距离顶部的位置 export const getDomOffset = { top: (node: any) => { let top = node.offsetTop; let parent = node.offsetParent; while (parent != null) { top += parent.offsetTop; parent = parent.offsetParent; } return top; }, left: (node: any) => { let top = node.offsetLeft; let parent = node.offsetParent; while (parent != null) { top += parent.offsetLeft; parent = parent.offsetParent; } return top; } };
传入对应的x和y坐标,popup自动跟随地图
发表评论
侧栏公告
寄语
譬如朝露博客是一个分享前端知识的网站,联系方式11523518。
热评文章
标签列表
热门文章
友情链接