解决react-map-gl与deck.gl屏幕外地图PDF截图不完整问题
问题原因
大尺寸页面(如A3横向)打印时,jsPDF默认仅能捕获浏览器视口内的内容,而基于WebGL渲染的deck.gl和react-map-gl图层,即便开启preserveDrawingBuffer={true},也会因地图容器尺寸未适配打印需求,只渲染视口可见区域。小尺寸页面能正常工作,是因为其整体尺寸处于浏览器视口范围内。
可行解决方案
1. 临时调整地图容器尺寸适配打印规格
打印前动态将地图容器的宽高修改为目标PDF页面的像素尺寸(需匹配PDF的DPI,比如默认72DPI下,A3横向的像素宽为1654、高为1169),等待地图完整渲染后恢复原尺寸,再执行PDF生成。
示例代码(在PrintMap组件中修改打印逻辑):
const handlePrint = async () => { const mapContainer = document.getElementById('map-container'); const originalStyle = { width: mapContainer.style.width, height: mapContainer.style.height }; // 按A3横向72DPI设置打印尺寸,可根据选择的页面类型动态切换 const printDims = { width: 1654, height: 1169 }; // 临时放大容器 mapContainer.style.width = `${printDims.width}px`; mapContainer.style.height = `${printDims.height}px`; // 给deck.gl足够时间渲染完整地图(时间可根据图层复杂度调整) await new Promise(resolve => setTimeout(resolve, 600)); // 生成PDF const doc = new jsPDF({ orientation: 'landscape', unit: 'px', format: [printDims.width, printDims.height] }); doc.html(mapContainer, { callback: (pdf) => { pdf.save('map.pdf'); // 恢复容器原尺寸 mapContainer.style.width = originalStyle.width; mapContainer.style.height = originalStyle.height; }, x: 0, y: 0 }); };
2. 强制地图组件重新渲染
调整容器尺寸后,通过修改组件key的方式,强制react-map-gl和DeckGL重新挂载并渲染完整区域:
示例代码(Map组件):
const Map = ({ isPrinting, printWidth, printHeight }) => { const mapStyle = { width: isPrinting ? `${printWidth}px` : '100%', height: isPrinting ? `${printHeight}px` : '100vh' }; return ( <div id="map-container" style={mapStyle}> <ReactMapGL key={isPrinting ? 'print-view' : 'normal-view'} preserveDrawingBuffer={true} // 其他地图props > <DeckGL key={isPrinting ? 'print-deck' : 'normal-deck'} preserveDrawingBuffer={true} // 其他DeckGL props /> </ReactMapGL> </div> ); };
3. 直接捕获DeckGL画布生成图片
跳过DOM捕获,直接提取DeckGL的WebGL画布转为图片,再添加到PDF中,确保内容完整:
示例代码:
const handlePrint = () => { const printDims = { width: 1654, height: 1169 }; const deckCanvas = document.querySelector('.deckgl-overlay canvas'); if (!deckCanvas) return; const doc = new jsPDF({ orientation: 'landscape', unit: 'px', format: [printDims.width, printDims.height] }); // 把画布转为图片添加到PDF const canvasData = deckCanvas.toDataURL('image/png'); doc.addImage(canvasData, 'PNG', 0, 0, printDims.width, printDims.height); doc.save('map.pdf'); };
注意事项
- 像素尺寸要和PDF的DPI匹配,比如使用300DPI时,A3横向的像素宽为6741、高为4799,需对应调整;
- 等待渲染的延迟时间需根据地图图层的数量和复杂度调整,避免因渲染未完成导致空白;
- 确保打印模式下,react-map-gl的viewport覆盖了完整的打印尺寸区域。
内容的提问来源于stack exchange,提问作者Hrutik
相关产品推荐
相关产品推荐

