天地图中使用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')}注意事项
- 天地图 API 版本差异:不同版本的天地图 class 名称可能不同,需要根据实际情况调整
- 测试验证:配置后务必测试,确保被忽略的元素不影响截图效果
- 性能考虑:
ignoreElements会对每个元素执行,保持回调函数简洁高效 - 跨域问题:如果还有跨域问题,可能需要在服务器端配置 CORS 响应头
总结
通过合理配置html2canvas的ignoreElements参数,可以有效避免重复加载天地图瓦片资源,解决资源耗尽问题。关键是要识别并过滤掉天地图相关的 DOM 元素。
关键词: html2canvas, 天地图, 资源耗尽, 截图优化, 前端性能
