Zhi-Ling

You can do Everything you want

0%

CreatePortal

Brief Intro: Easy way to mount virtual react dom to GisMap under restricted accepting types circumstances

背景

业务需求基于 mapoboxgl 封装二维 gis 地图,支持打点,画线及绘制面,即业务上的坐标点、轨迹线条和电子围栏区域。

createPortal 原理

  • Portal 将提供一种将子节点渲染到 DOM 节点中的方式,该节点存在于 DOM 组件的层次结构之外。
  • 适合脱离文档流 (out of flow) 的组件,特别是 position: absolute 与 position: fixed 的组件。比如模态框,通知,警告,goTop 等

使用场景

场景一:坐标点点击后弹框显示

官方示例 << 传送门

限制

  • 接受类型有限(当前官方示例中仅写了 HTML 和 DomContent)
  • 原生样式及标签写法较为麻烦
  • 数据量庞大的时候难以受控单个点位
  • 可扩展性不高,维护起来难度高
  • 组件视角看,不方便开发绘制定制化的展示内容

扩展方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 首先创建一个DOM容器,用来嵌入业务中传入的自定义内容组件
const popupContentDom = document.createElement("div");

const popup = new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setDOMContent(popupContentDom)
.addTo(map);

// 由于popup是mapboxgl内部提供的弹框方式,父容器已经绑定到mapboxgl
// 只要在渲染的地方通过createPortal把接收到的子组件挂载到popupContentDom下
return (
<React.Fragment>
<MapGIS xxx />
{/* 这里是通过props.children的方式接受自定义内容组件 */}
{props.children && ReactDOM.createPortal(props.children, popupContentDom)}
</React.Fragment>
);

场景二:自定义图标组件渲染到 gis 地图上

背景

业务需要支持公司内部封装的图标组件渲染到 gis 地图上,通过调研发现可以使用 mapboxgl 的 Marker 进行标记点的添加,最后同样的方式挂载到地图上。

使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 注意:因为要接受自定义图标组件,这里要挂载的父容器变成了markerComp
const markerComp = document.createElement("div");

const marker = new mapboxgl.Marker(markerComp)
.setLngLat({ lng, lat })
.addTo(map);

const popup = new mapboxgl.Popup().setDOMContent(popupContentDom);
marker.setPopup(popup);

return (
<React.Fragment>
<MapGIS xxx />
{/* 这里是通过props.children的方式接受自定义内容组件 */}
{ReactDOM.createPortal(["自定义组件"], markerComp)}
</React.Fragment>
);

弊端

地图组件内容本身要处理例如瓦片, 图层(layer)数据源(source)标记点线条图像 等渲染以及原生事件,因此如果当 marker 点位过多的时候会影响地图加载速度。

解决方式

… 下篇文章

Welcome to my other publishing channels