React-Leaflet-v3 可重用自定义控件
React-Leaflet-v3 Reusable Custom Control
背景
对于 React Leaflet v2,有一个 NPM 插件 react-leaflet-control,它允许您创建任何类型的控件并将其放入 react-leaflet 控件容器中。显然,随着 RL-v3 的引入,这在具有 API 更改的 v3 中不再适用。我想创建一个自定义控件包装器以允许我在其中放置任何类型的 React 节点。
当前状态
我目前拥有的代码可以工作...但不能。我从 Stack Overflow post: 中的示例中提取了创建自定义控件的 99% 解决方案。但是,我的用例是地图上的工具栏,带有可交互的按钮(指定活动工具的颜色)。然而,使用这段代码,我有那个功能,但是因为每次渲染都会导致创建一个新控件,工具提示会闪烁,因为它正在丢失它的锚元素。
期望的行为
我想要一个允许用户使用 select 工具在地图上执行操作的工具栏(想想老派 leaflet-draw
。为了提供反馈,我希望按钮在工具处于活动状态,对于 UX,我希望工具提示能够描述按钮的操作。
实际行为
工具栏存在,用户可以 select 工具,并且有 UI 反馈,但是,当 select使用工具。
代码沙箱
我最终得到了一个接受@teddybeard 所说内容的答案。如果我只是按照建议用 class 创建了新的 div
,它将被放置在任何默认控件之上,例如 ZoomControl
或 ScaleControl
。相反,我所做的是从 DOM 中获取实际位置 div
容器,然后在该容器中创建一个 ReactDOM 门户并以这种方式添加我的控件。
它有效,没有由于 React Effect 在每个渲染上删除并重新添加控件而导致的视觉闪烁问题,我仍然得到相同的定位。
它在 npm 和 github https://github.com/chris-m92/react-leaflet-custom-control and https://npmjs.com/package/react-leaflet-custom-control
上直播
const POSITION_CLASSES = {
bottomleft: 'leaflet-bottom leaflet-left',
bottomright: 'leaflet-bottom leaflet-right',
topleft: 'leaflet-top leaflet-left',
topright: 'leaflet-top leaflet-right',
}
const Control = (props: Props): JSX.Element => {
const [container, setContainer] = React.useState<any>(document.createElement('div'))
const positionClass = (props.position && POSITION_CLASSES[props.position] || POSITION_CLASSES.topright)
React.useEffect(() => {
const targetDiv = document.getElementsByClassName(positionClass)
setContainer(targetDiv[0])
}, [])
const controlContainer = (
<div className='leaflet-control leaflet-bar'>{props.children}</div>
)
L.DomEvent.disableClickPropagation(container)
return ReactDOM.createPortal(
controlContainer,
container
)
}
export default Control
背景
对于 React Leaflet v2,有一个 NPM 插件 react-leaflet-control,它允许您创建任何类型的控件并将其放入 react-leaflet 控件容器中。显然,随着 RL-v3 的引入,这在具有 API 更改的 v3 中不再适用。我想创建一个自定义控件包装器以允许我在其中放置任何类型的 React 节点。
当前状态
我目前拥有的代码可以工作...但不能。我从 Stack Overflow post:
期望的行为
我想要一个允许用户使用 select 工具在地图上执行操作的工具栏(想想老派 leaflet-draw
。为了提供反馈,我希望按钮在工具处于活动状态,对于 UX,我希望工具提示能够描述按钮的操作。
实际行为
工具栏存在,用户可以 select 工具,并且有 UI 反馈,但是,当 select使用工具。
代码沙箱
我最终得到了一个接受@teddybeard 所说内容的答案。如果我只是按照建议用 class 创建了新的 div
,它将被放置在任何默认控件之上,例如 ZoomControl
或 ScaleControl
。相反,我所做的是从 DOM 中获取实际位置 div
容器,然后在该容器中创建一个 ReactDOM 门户并以这种方式添加我的控件。
它有效,没有由于 React Effect 在每个渲染上删除并重新添加控件而导致的视觉闪烁问题,我仍然得到相同的定位。
它在 npm 和 github https://github.com/chris-m92/react-leaflet-custom-control and https://npmjs.com/package/react-leaflet-custom-control
上直播const POSITION_CLASSES = {
bottomleft: 'leaflet-bottom leaflet-left',
bottomright: 'leaflet-bottom leaflet-right',
topleft: 'leaflet-top leaflet-left',
topright: 'leaflet-top leaflet-right',
}
const Control = (props: Props): JSX.Element => {
const [container, setContainer] = React.useState<any>(document.createElement('div'))
const positionClass = (props.position && POSITION_CLASSES[props.position] || POSITION_CLASSES.topright)
React.useEffect(() => {
const targetDiv = document.getElementsByClassName(positionClass)
setContainer(targetDiv[0])
}, [])
const controlContainer = (
<div className='leaflet-control leaflet-bar'>{props.children}</div>
)
L.DomEvent.disableClickPropagation(container)
return ReactDOM.createPortal(
controlContainer,
container
)
}
export default Control