使用react-leaflet在标记内实现动态JSX元素

2023-12-25

我有一个正在使用的 React 应用程序Leaflet http://leafletjs.com/通过反应传单 https://github.com/PaulLeCam/react-leaflet,两个超级有用的库。

在这个应用程序中,我有一组需要渲染的坐标,如下所示:

  1. When zoomed out, cluster the coordinates into Marker Clusters like so enter image description here

  2. 放大时,每个标记需要有

    1. 其下方有一个动态倒计时器
    2. A dynamic SVG countdown clock around it like so enter image description here

对于聚类,我使用的是反应传单标记簇 https://www.npmjs.com/package/react-leaflet-markercluster插件,非常适合显示静态内容。

但是,当我需要在每个标记中显示任何动态内容时,我无法选择发送JSX,仅提供静态 HTML,如可用示例所示here https://yuzhva.github.io/react-leaflet-markercluster/#marker-popup.

// Template for getting popup html MarkerClusterGroup
// IMPORTANT: that function returns string, not JSX
function getStringPopup(name) {
  return (`
    <div>
      <b>Hello world!</b>
      <p>I am a ${name} popup.</p>
    </div>
  `);
}

// that function returns Leaflet.Popup
function getLeafletPopup(name) {
  return L.popup({ minWidth: 200, closeButton: false })
    .setContent(`
      <div>
        <b>Hello world!</b>
        <p>I am a ${name} popup.</p>
      </div>
    `);
}

有办法处理这种情况吗?如何制作 JSX 标记而不是静态 HTML 标记?

PS:我尝试过使用ReactDOM.renderToString已经,但这是一个丑陋的黑客,并且每次都需要重新渲染标记。

TIA!!

这是一个示例WebpackBin https://www.webpackbin.com/bins/-KxhoIKcuQaFNyL7zivs如果您心中有解决方案,可以尝试一下


我现在找到了一些将自定义 JSX 渲染为标记的工作代码。

这是95%的副本https://jahed.dev/2018/03/20/react-portals-and-leaflet/ https://jahed.dev/2018/03/20/react-portals-and-leaflet/以及 5% 的灵感来自https://github.com/PaulLeCam/react-leaflet/blob/master/packages/react-leaflet/src/Marker.tsx https://github.com/PaulLeCam/react-leaflet/blob/master/packages/react-leaflet/src/Marker.tsx

我确信有些事情可以进一步优化。

import * as React from 'react';
import { createPortal } from "react-dom";
import { DivIcon, marker } from "leaflet";
import * as RL from "react-leaflet";
import { MapLayer } from "react-leaflet";
import { difference } from "lodash";

const CustomMarker = (RL as any).withLeaflet(class extends MapLayer<any> {
    leafletElement: any;
    contextValue: any;

    createLeafletElement(props: any) {
        const { map, layerContainer, position, ...rest } = props;

// when not providing className, the element's background is a white square
// when not providing iconSize, the element will be 12x12 pixels
        const icon = new DivIcon({ ...rest, className: '', iconSize: undefined });

        const el = marker(position, { icon: icon, ...rest });
        this.contextValue = { ...props.leaflet, popupContainer: el };
        return el;
    }

    updateLeafletElement(fromProps: any, toProps: any) {
        const { position: fromPosition, zIndexOffset: fromZIndexOffset, opacity: fromOpacity, draggable: fromDraggable, className: fromClassName } = fromProps;
        const { position: toPosition, zIndexOffset: toZIndexOffset, toOpacity, draggable: toDraggable, className: toClassName } = toProps;

        if(toPosition !== fromPosition) {
            this.leafletElement.setLatLng(toPosition);
        }
        if(toZIndexOffset !== fromZIndexOffset) {
            this.leafletElement.setZIndexOffset(toZIndexOffset);
        }
        if(toOpacity !== fromOpacity) {
            this.leafletElement.setOpacity(toOpacity);
        }
        if(toDraggable !== fromDraggable) {
            if(toDraggable) {
                this.leafletElement.dragging.enable();
            } else {
                this.leafletElement.dragging.disable();
            }
        }
        if(toClassName !== fromClassName) {
            const fromClasses = fromClassName.split(" ");
            const toClasses = toClassName.split(" ");
            this.leafletElement._icon.classList.remove(
                ...difference(fromClasses, toClasses)
            );
            this.leafletElement._icon.classList.add(
                ...difference(toClasses, fromClasses)
            );
        }
    }

    componentWillMount() {
        if(super.componentWillMount) {
            super.componentWillMount();
        }
        this.leafletElement = this.createLeafletElement(this.props);
        this.leafletElement.on("add", () => this.forceUpdate());
    }

    componentDidUpdate(fromProps: any) {
        this.updateLeafletElement(fromProps, this.props);
    }

    render() {
        const { children } = this.props;
        const container = this.leafletElement._icon;

        if(!container) {
            return null;
        }

        const portal = createPortal(children, container);

        const LeafletProvider = (RL as any).LeafletProvider;

        return children == null || portal == null || this.contextValue == null ? null : (
            <LeafletProvider value={this.contextValue}>{portal}</LeafletProvider>
        )
    }
});

然后在你的组件中使用它,如下所示:

<Map ...>
  <CustomMarker position={[50, 10]}>
    <Tooltip>
      tooltip
    </Tooltip>
    <Popup>
      popup
    </Popup>
    
    <div style={{ backgroundColor: 'red' }} onClick={() => console.log("CLICK")}>
      CUSTOM MARKER CONTENT
    </div>
    MORE CONTENT
  </CustomMarker>
</Map>

如果你不使用 TypeScript。只需删除as any and : any stuff.


编辑:某些东西会自动设置width: 12px; and height: 12px;。我还不确定如何防止这种情况。其他一切似乎都工作正常!

编辑2:修复它!使用iconSize: undefined


EDIT3:还有这个:https://github.com/OpenGov/react-leaflet-marker-layer https://github.com/OpenGov/react-leaflet-marker-layer还没有测试过,但示例代码看起来不错。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用react-leaflet在标记内实现动态JSX元素 的相关文章

随机推荐

  • 无需 Foreach 循环即可访问 LINQ 结果中的行?

    对于我编写的每个 LINQ 查询 我总是使用 foreach 循环来遍历结果 现在 我有一个程序 我想获取结果的前 50 行 对这些行进行一些计算 然后获取结果的接下来 50 行等 使用 LINQ 和 C 执行此操作的良好标准方法是什么 在
  • Sass 导入而不编译

    在 sass 中 导入的方式是使用 import 命令 我将以 Zurb 基金会为例 import foundation 然后这将导入整个foundation scss文件及其所有相对导入到当前文件顶部的内容 这意味着整个foundatio
  • 使用 document.getElementById 注入元素在 Javascript 中不起作用

    我已经编写了一小段 JavaScript 代码 现在需要将结果注入到我的 HTML 中 我已经检查了 windows 元素 甚至复制了该元素的特定选择器 但它仍然没有将答案注入其中 我正在尝试将其插入 HTML 代码中的 span 标记中
  • HTML Agility 包创建新的 HTMLNode

    我正在使用 HTML Agility Pack 来解析和转换 HTML 文件 但由于索引参数而尝试创建新的 HTMLNode 时 出现 项目已添加 异常 HtmlNode node1 new HtmlNode HtmlNodeType El
  • 如何为 AWS V3 Dynamodb 客户端设置超时

    我已经开始在我的一些服务中使用新的 AWS 版本 3 sdk 不幸的是 并不总是清楚如何使用版本 2 sdk 中提供的模块化版本 3 代码中的某些功能 要为非模块化 sdk 设置超时 您可以执行以下操作 AWS config update
  • STS 3.4.0 与 Websphere 8.5.5.0 不部署我的应用程序

    我尝试从 Eclipse 将我的应用程序部署到 WebSphere 上 这里有一些条件 STS 3 4 0 Websphere 插件 适用于 Kepler Luna 的 IBM WebSphere Application Server V8
  • Solr:基于字段的存在进行提升,忽略该字段的内容

    我想根据文档中某个字段的存在来增强查询 而不管该字段的内容如何 假设某个文档有一个包含照片 id 值的字段 我希望在搜索时首先出现包含照片的文档 照片 ID 值与搜索查询无关 但该字段的存在才是重要的 怎么做 如上所述here http w
  • 在 Yii 中从数据库生成树

    我在 Yii 中有一个模型 它代表一棵树 具有以下 MySQL 表 CREATE TABLE IF NOT EXISTS nodes id int 11 NOT NULL AUTO INCREMENT node varchar 255 NO
  • 如何停止 UIView 可能不响应选择器的警告

    我有一个具有 UIView 作为属性的类 有时我会传入一个 UILabel 有时是 UITextField 无论我传入哪个 我都希望班级设置文本 目前我正在这样做 它有效 if self viewToUpdate respondsToSel
  • 是否可以获得MySQL所有系统函数的列表?

    我看起来像 SHOW FUNCTION STATUS 获取当前服务器版本的所有可用系统功能的列表 可以得到这样的表here http dev mysql com doc refman 5 6 en string functions html
  • 如何对命名空间中的模型执行 has_many

    Rails 3 为我们提供了这些漂亮的生成器 可以将模型和控制器放入命名空间中 哇 但现在我无法将它们与其他模型联系起来 我试图通过与命名空间模型关联来实现 has many 我已经在互联网上搜索了几天 但还没有想出任何例子 app mod
  • 嵌入式 Python 3.5“python setup.py Egg_info”失败,错误代码为 1

    我正在尝试 pip install PyAutoGUI 以及其他模块 但收到以下错误 Collecting pyautogui Using cached PyAutoGUI 0 9 35 zip Complete output from c
  • 为什么被删除:ASP.NET MVC CheckBoxList(没有MVCContrib)

    为什么是复选框列表从 ASP NET MVC 预览版本 5 中删除 目前 我没有看到任何可以创建复选框列表 具有相似名称但不同 id 的方法 以便人们可以从列表中选择 0 1 更多选项 有一个CheckBoxList列表存在于 MVCCon
  • 使用 python 更新 CKAN 中的资源

    我正在尝试更新 CKAN 的一个实例中的资源 我正在使用 demo ckan org 进行一些测试 我可以使用以下命令创建和更新数据集的资源curl 但是使用 python 我无法做到这一点 我的起点是这个链接 http docs ckan
  • 设置 Windows 文件共享的权限

    我有以下代码 该代码应该遍历文件共享中的文件夹并将其中的任何权限转换为读取权限 但是 存在一个问题 它不会替换已有的权限 而只是添加到其中 其次 如果该文件夹没有继承权限 则会给出错误消息 Set Acl 进程不拥有此操作所需的 SeSec
  • 将 utf-16 字符串传递给 Windows 函数

    我有一个名为 some dll 的 Windows dll 具有以下功能 void some func TCHAR input string some func 需要一个指向 utf 16 编码字符串的指针 运行这个Python代码 fro
  • 按经纬度查找电话区号

    寻找一种方法来获取给定纬度和经度的电话区号列表 如果需要 还可以提供给定的国际代码 请注意 我不是在谈论国际拨号前缀 而是在谈论其中的区号 例如 科罗拉多州丹佛市的区号为 303 和 720 其位置为 39 739 104 985 位于 N
  • Kotlin:如何从另一个 IntelliJ 模块导入类?

    我在 IntelliJ 中有一个简单的 Kotlin 项目 其中两个模块定义为项目根文件夹下的子文件夹 一切似乎都在构建设置中正确设置 每个模块都有自己的文件夹标记为源目录 我可以在两个模块中运行主要功能 因此 IntelliJ 发现一切正
  • mongodb 上的多重求和/计数(性别总和以及所有结果总计)

    我有这个文件 gender male gender male gender female gender female gender female 所以 我需要像这样检索 total 5 male 2 female 3 我的实际查询 没有工作
  • 使用react-leaflet在标记内实现动态JSX元素

    我有一个正在使用的 React 应用程序Leaflet http leafletjs com 通过反应传单 https github com PaulLeCam react leaflet 两个超级有用的库 在这个应用程序中 我有一组需要渲