React-Leaflet-v3 可重用自定义控件

c-m*_*b92 2 leaflet reactjs react-leaflet react-leaflet-v3

背景

对于React Leaflet v2,有一个NPM插件react-leaflet-control,它允许您创建任何类型的控件并将其放入react-leaflet控件容器中。显然,随着 RL-v3 的引入,随着 API 的更改,这在 v3 中不再适用。我想创建一个自定义控件包装器,以允许我在其中放置任何类型的 React Node。

当前状态

我目前拥有的代码可以工作......但不能。我从 Stack Overflow 帖子中的示例中提取了内容:React Leaflet V3 Custom Control,它让我获得了创建自定义控件的 99% 解决方案。但是,我的用例是地图上的工具栏,其中包含可交互的按钮(颜色用于指定活动工具)。然而,通过这段代码,我拥有了该功能,但由于每次渲染都会导致创建一个新控件,因此工具提示会在失去其锚元素时闪烁。

期望的行为

我想要一个工具栏,允许用户选择工具在地图上执行操作(想想老式的)leaflet-draw。为了提供反馈,我希望按钮在工具处于活动状态时改变颜色,对于用户体验,我想要工具提示来描述操作按钮的。

实际行为

工具栏存在,用户可以选择工具并且有 UI 反馈,但是,当选择工具时在每个渲染上删除并重新添加控件时,工具提示会丢失其锚元素。

代码沙箱

https://codesandbox.io/s/react-leaflet-custom-control-n1xpv

c-m*_*b92 9

我最终得到了一个类似于 @teddybeard 所说的答案。如果我只是div按照建议使用类创建了新的控件,它将被放置在任何默认控件的顶部,例如ZoomControlScaleControl。相反,我所做的是div从 DOM 中获取实际位置容器,然后在该容器中创建一个 ReactDOM 门户,并以这种方式添加我的控件。

它有效,不存在视觉闪烁的问题,因为 React Effect 在每个渲染上删除并重新添加控件,而且我仍然得到相同的定位。

它在 npm 和 github 上上线:https://github.com/chris-m92/react-leaflet-custom-controlhttps://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
Run Code Online (Sandbox Code Playgroud)