百度地图海量点方案趟坑记录(百度地图GL版 + MapVGL + vue3 + ts)

核心需求描述

  1. 不同层级有不同的海量图标展示
  2. 底层海量图标需要展示文字
  3. 拖动、放大缩小都需要重新请求数据并展示
  4. 固定地图中心点(拖动、放大缩小,中心点始终在地图中心)
    示例图片: (某些图片涉及公司数据,就未展示了!2024-02-20 删除)

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ff309375caf542f3a8c177ea6c1acece.png![在这里插入图片描述](https://file.jishuzhan.net/article/1761308004717694978/034f5b2ce643bc1857d71d44248b00b2.webp)

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c03b7756e0f14f48b2c74709b242f9a6.png![在这里插入图片描述](https://file.jishuzhan.net/article/1761308004717694978/612a6d45d6ee38cec7b05591e84c71e1.webp)

技术方案

  • vue3 + ts
  • 百度地图GL版(第一版为2d版,后因性能、用户体验等废弃)
  • MapVGL

遇到的问题

  1. 百度地图文档不全,某些方法需要打印实例查看
  2. MapVGL 文档不全,需要的某个功能在示例中存在,而文档中没有
  3. 缩放时中心点会偏移
  4. mapvgl 图标,在地图中消失,但点击所在位置还能响应相关事件
  5. 重复绘制次数太多,且图片会闪动,(也是内存溢出的原因之一)
  6. 内存溢出(原因之一:热力图层)

解决方案

前两点无解,官方不作为,只能大家辛苦点,自己多方面去搜寻想要的东西。

3 缩放时中心点会偏移

百度地图缩放时,是按照当前鼠标位置为缩放的基点,在移动端则为两指之间的中心点,所以在我们当前的场景下缩放时,就会产生中心点偏移的情况,解决方案逻辑:

*仅针对移动端
监听百度地图容器的 touchmove 事件替换地图自身的双指缩放,通过两点之间的距离判断放大/缩小,去设置百度地图的层级

部分逻辑代码如下:

html 复制代码
  <XCMap ref="xcMapRef"  @touchend="ontouchend" @touchmove="ontouchMove" @touchstart="ontouchstart" ... />
ts 复制代码
const { start, move, end } = useCalcDistance(); // 将相关触摸事件及计算距离等,提取成了 useHooks 

const ontouchstart = (e: TouchEvent) => {
    start(e.touches); // 开始事件中会计算存储一个基础值
};

const ontouchMove = (e: TouchEvent) => {
    move(e.touches, (k) => { // move 事件中会通过基础值计算出是放大还是缩小
        let zoom = centerAndZoom.value.zoom; // 这里是当前地图的 zoom 值
        if (k === 'zoomIn') {  // 放大
            zoom += 0.1;// 层级加 0.1 (数值可以根据具体情况变更)
            if (zoom >= MAX_LAYER) { // 如果层级大于等于我们预设的最大值时,就设为最大值
                zoom = MAX_LAYER;
            }
        } else if (k === 'zoomOut') { // 缩小
            zoom -= 0.1; // 层级减 0.1 (数值可以根据具体情况变更)
            if (zoom <= MIN_LAYER) { // 如果层级小于等于我们预设的最小值时,就设为最小值
                zoom = MIN_LAYER;
            }
        }
        centerAndZoom.value.zoom = zoom;  // 计算结束去设置当前地图的 zoom 值
    });
};

const ontouchend = () => {
    end(); // end 事件中会去重置一些基础数据
};

4 mapvgl 图标,在地图中消失,但点击所在位置还能响应相关事件

当前地图页面(做了keep alive)绘制 icon 图标后,去往其它页面再返回,地图上图标丢失,但点击 之前 icon的位置,还是能响应点击事件。

这个问题的原因,没有过多的去排查,应该是 keep alive 造成的,所以解决方案就是取消当前页面的缓存机制,采用 vuex 去存储当前页面数据,每次都是重新进入页面渲染,就可以解决此问题。

5 重复绘制次数太多,且图片会闪动,(也是内存溢出的原因之一)

业务逻辑中,每次拖动地图,都会重新请求数据,并渲染到地图中,造成图片闪动的问题有以下两个方面:

1 获取的数据数量巨大。

2 之前的逻辑是每次都情况地图数据,重新渲染。

3 触发绘制的事件太多,如:拖动、放大、缩小、过滤条件筛选等

解决方案如下:

1 针对图片闪动,采取在获取数据后重新渲染之前,使用缓存数据生成一个层覆盖地图上,当新数据重新渲染后再删除缓存层:

ts 复制代码
        ...other code
        let layerCache: MapVGL2.LayerCache; // 生命一个缓存层
        layerCache = this[layerType]; // 将旧层数据赋值给缓存层
        this[layerType] = new window.mapvgl[currentConfig.funName](currentConfig.options); // 生成新的层
        this.mapvglView?.addLayer(this[layerType]); // 添加到地图中
        setTimeout(() => {
            !!layerCache && this.mapvglView?.removeLayer(layerCache);
            layerCache?.clear()
            layerCache?.destroy()
            layerCache = null;
        }, 20) // 20 毫秒后删除缓存层
      ...other code

2 对绘制事件做防抖处理,减少绘制事件的触发频次,使用的时 lodash 的方法

ts 复制代码
import { debounce } from 'lodash';

const draw = debounce(() => {
...
})

6 内存溢出(原因之一:热力图层)

针对内存溢出,排查出是图层清理不干净导致,排查很久发现 MapVgl 的热力图层和其它图层不一样,并不能正常的删除,

所以在渲染绘制的时候,其它图层可以正常使用 api 去清空删除,热力图则只初始化一次,每次热力图数据有变化,只更新此图层数据不做重新初始化处理,其次针对数据量太大,也对某些图层做了数据缓存对比处理,针对存在的数据不做清空处理,减少清空渲染时的一些资源消耗。

其它。。。
(因为是几个月前的事情了,没有及时记录,现在有点忘了,待想起补充!)

相关推荐
一个处女座的程序猿O(∩_∩)O8 分钟前
完成第一个 Vue3.2 项目后,这是我的技术总结
前端·vue.js
mubeibeinv9 分钟前
项目搭建+图片(添加+图片)
java·服务器·前端
逆旅行天涯15 分钟前
【Threejs】从零开始(六)--GUI调试开发3D效果
前端·javascript·3d
m0_7482552636 分钟前
easyExcel导出大数据量EXCEL文件,前端实现进度条或者遮罩层
前端·excel
web147862107231 小时前
C# .Net Web 路由相关配置
前端·c#·.net
m0_748247801 小时前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
飞的肖1 小时前
前端使用 Element Plus架构vue3.0实现图片拖拉拽,后等比压缩,上传到Spring Boot后端
前端·spring boot·架构
青灯文案11 小时前
前端 HTTP 请求由 Nginx 反向代理和 API 网关到后端服务的流程
前端·nginx·http
m0_748254881 小时前
DataX3.0+DataX-Web部署分布式可视化ETL系统
前端·分布式·etl
ZJ_.2 小时前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps