【问题标题】:React-Leaflet-v3 Reusable Custom ControlReact-Leaflet-v3 可重用的自定义控件
【发布时间】:2021-10-23 02:42:36
【问题描述】:

背景

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

当前状态

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

期望的行为

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

实际行为

工具栏存在,用户可以选择工具并且有 UI 反馈,但是,工具提示会丢失它们的锚元素,因为在选择工具时,每次渲染时都会删除并重新添加控件。

代码沙盒

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

【问题讨论】:

  • 你的方法不是很'react-ey'。 Reacts 的主要工作是快速重新渲染 HTML。 Leaflet 也可以使用DomUtil 渲染 HTML,但它的设计目的不是为了反复重新渲染它。你能不使用 L.control 只用 HTML 编写你的控件吗?
  • 100% 有效它不是很反应,因为它直接在 React 之外操作 DOM。我明白了。我喜欢它在 Leaflet 的“控制”结构中的原因是利用该样式在地图上定位,而不是在屏幕上使用其他 CSS 绝对定位。我已经用不同的反应组件做到了这一点,但希望它与地图集成。可能无法再使用 v3

标签: reactjs leaflet react-leaflet react-leaflet-v3


【解决方案1】:

我最终得到了一个类似于 @teddybeard 所说的答案。如果我刚刚使用建议的类创建了新的div,它将被放置在任何默认控件之上,例如ZoomControlScaleControl。相反,我所做的是从 DOM 中获取实际位置 div 容器,然后在该容器中创建一个 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

【讨论】:

  • 优秀的解决方案。以前没有使用过 createPortal,但它似乎是连接 React 和 Leaflet 现有 DOM 元素的一个很好的桥梁。干得好!
猜你喜欢
  • 2020-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
相关资源
最近更新 更多