![](/img/trans.png)
[英]How to reproject layers (using GeoServer and OpenLayers) in order to overlay on the google maps
[英]How to manage OpenLayers Overlay lifecycle using React?
给定一个使用 OpenLayers 渲染交互式地图的 React 应用程序,我想为显示的功能提供工具提示。 生命周期应如下所示:地图上没有或只有一个工具提示。 如果用户在某个要素的特定距离内单击,工具提示会出现在该要素在地图上的位置附近,如果之前有工具提示,则会被新工具提示替换。 如果用户单击附近没有要素的地图部分,则先前的工具提示将被破坏。
我已经尝试了多种实现这种逻辑的方法,但最后一个让我无法成功的逻辑缺陷是当 React 想要卸载一个工具提示组件时,它无法找到它,因为 OpenLayers 将它移到了它自己的ol-overlay-container
容器中.
正如在对类似问题的回答中所建议的那样,一个可能的解决方案是使用 react 的createPortal
将工具提示直接呈现到 openlayers 无论如何都会将其复制到的 DOM 位置。 这个问题似乎是 openlayers 仍然包裹了元素,使得在卸载时无法做出反应来移除它。
到目前为止,这是我的弹出/工具提示组件代码:
import { Overlay } from "ol"
import { createRef, useEffect, useRef, useState } from "react"
import { createPortal } from "react-dom"
import useMap from "../../Hook/useMap"
const Popup = ({ feature, position, ...props }) => {
const { map } = useMap() // custom map context
const overlay = useRef()
const [domReady, setDomReady] = useState(false)
const overlayContainer = useRef()
const overlayContent = createRef()
useEffect(() => {
setDomReady(true)
overlayContainer.current = document.getElementsByClassName(
"ol-overlay-container ol-selectable"
)[0]
return () => {
setDomReady(false)
}
}, [])
useEffect(() => {
if (domReady && overlayContainer.current) {
overlay.current = new Overlay({
element: overlayContainer.current,
id: "popup",
})
if (position) {
overlay.current.setPosition(position)
}
map.addOverlay(overlay.current)
return () => {
map.removeOverlay(overlay.current)
}
}
}, [domReady, feature, position])
return domReady
? createPortal(
<div className="test-overlay" ref={overlayContent}>
{props.children}
</div>,
overlayContainer.current
)
: null
}
export default Popup
这就要求在应用程序的整个生命周期中都存在类名为ol-overlay-container ol-selectable
。 默认情况下,它似乎只有在将叠加层添加到地图后才会创建。 因此,我用一个空覆盖层初始化我的地图,其元素是我在 index.html 中创建的一个div
:
const map = new OlMap({
overlays: [
new Overlay({
id: "preserveOverlayContainer",
element: document.getElementById("map-overlay"),
position: [0, 0],
}),
],
...
})
有没有办法让工具提示包含由 React 管理的内容,但使用 openlayers 渲染到地图中?
与此同时,我想出了一个 hacky,但看似可行的解决方案:
return () => {
map.removeOverlay(overlay.current)
const outer = document.createElement("div")
outer.id = "map-overlay-outer"
document.body.appendChild(outer)
overlayContainer.current = document.getElementById("map-overlay-outer")
}
在第二个useEffect
的清理函数中, removeOverlay()
方法调用将之前呈现的工具提示从 DOM 中完全移除,因此我们只需重新创建它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.