天地图中使用html2canvas问题

解决 html2canvas 导致天地图资源耗尽问题

问题背景

在使用html2canvas对包含天地图的页面进行截图时,发现会重复请求地图瓦片资源,导致:

  • 网络请求数激增
  • 地图 API 配额快速耗尽
  • 页面性能下降

问题原因

html2canvas的工作原理是遍历 DOM 树并重新渲染每个元素。当遇到<img><canvas>等元素时,它会尝试重新加载这些资源。

天地图使用<img>标签或 Canvas 来加载瓦片图片,当html2canvas遇到这些元素时,会重新发起请求加载瓦片,而不是直接使用已缓存的资源。

解决方案

1. 使用ignoreElements过滤地图元素

importhtml2canvasfrom"html2canvas"constcanvas=awaithtml2canvas(element,{backgroundColor:null,allowTaint:false,// 启用 CORS 支持useCORS:true,// 关键:忽略天地图相关元素ignoreElements:(element)=>{returnelement.classList&&(element.classList.contains('tdt-tile')||element.classList.contains('tdt-overlay-pane')||element.tagName==='CANVAS'&&element.parentElement?.classList?.contains('tdt-map-pane'))}})

2. 参数说明

参数作用
useCORS: true启用跨域资源共享,避免因跨域导致重复请求
ignoreElements回调函数,返回true表示忽略该元素
tdt-tile天地图瓦片元素的 class
tdt-overlay-pane天地图覆盖层的 class

3. 完整示例

<template> <div ref="captureElement"> <!-- 需要截图的内容 --> <div class="custom-content">自定义内容</div> </div> </template> <script setup> import { ref } from 'vue' import html2canvas from 'html2canvas' const captureElement = ref(null) const captureToImage = async () => { try { const canvas = await html2canvas(captureElement.value, { backgroundColor: null, allowTaint: false, useCORS: true, ignoreElements: (element) => { return element.classList && ( element.classList.contains('tdt-tile') || element.classList.contains('tdt-overlay-pane') || element.tagName === 'CANVAS' && element.parentElement?.classList?.contains('tdt-map-pane') ) } }) // 转换为 Base64 const imageData = canvas.toDataURL('image/png') return imageData } catch (error) { console.error('截图失败:', error) } } </script>

其他优化建议

1. 避免频繁调用

// 使用防抖避免频繁截图import{debounce}from'lodash-es'constdebouncedCapture=debounce(async()=>{constimageData=awaitcaptureToImage()// 处理图片},300)

2. 使用缓存机制

constimageCache=newMap()constcaptureToImage=async(key)=>{// 检查缓存if(imageCache.has(key)){returnimageCache.get(key)}constimageData=awaithtml2canvas(element,options)imageCache.set(key,imageData)returnimageData}

3. 限制截图区域

如果不需要截取整个地图,可以先克隆 DOM 并移除地图相关元素:

constcaptureWithoutMap=async(originalElement)=>{// 克隆元素constclone=originalElement.cloneNode(true)// 移除地图容器constmapContainer=clone.querySelector('.tdt-map-container')if(mapContainer){mapContainer.remove()}constcanvas=awaithtml2canvas(clone,{...options})returncanvas.toDataURL('image/png')}

注意事项

  1. 天地图 API 版本差异:不同版本的天地图 class 名称可能不同,需要根据实际情况调整
  2. 测试验证:配置后务必测试,确保被忽略的元素不影响截图效果
  3. 性能考虑ignoreElements会对每个元素执行,保持回调函数简洁高效
  4. 跨域问题:如果还有跨域问题,可能需要在服务器端配置 CORS 响应头

总结

通过合理配置html2canvasignoreElements参数,可以有效避免重复加载天地图瓦片资源,解决资源耗尽问题。关键是要识别并过滤掉天地图相关的 DOM 元素。


关键词: html2canvas, 天地图, 资源耗尽, 截图优化, 前端性能