React+OpenLayers中如何将Canvas无变形导出为PDF
我之前在做OpenLayers+React项目时也踩过jsPDF导出Canvas变形的坑,大概率是像素比例不匹配或者尺寸单位没搞对。下面几个方案应该能帮你解决问题:
解决OpenLayers Canvas导出PDF变形的具体方案
1. 先搞清楚Canvas的「真实尺寸」
OpenLayers的Canvas会根据设备像素比(devicePixelRatio)自动调整实际绘制像素,和DOM元素显示的宽高可能不一样。别直接拿DOM的offsetWidth/offsetHeight,要取Canvas的原生宽高或者从Map实例获取:
// 方法1:直接获取Canvas元素的真实像素 const mapCanvas = document.querySelector('.ol-unselectable'); const canvasWidth = mapCanvas.width; const canvasHeight = mapCanvas.height; // 方法2:从OpenLayers Map实例获取更准确的尺寸 const viewSize = map.getSize(); const pixelRatio = map.getPixelRatio(); const actualWidth = viewSize[0] * pixelRatio; const actualHeight = viewSize[1] * pixelRatio;
2. 初始化jsPDF时匹配尺寸单位
jsPDF默认用mm作为单位,直接塞像素值肯定会缩放混乱。建议用px作为单位,要么直接把PDF页面设成Canvas的真实尺寸,要么按比例缩放到标准页面(比如A4):
import jsPDF from 'jspdf'; // 方案A:让PDF页面完全匹配Canvas尺寸 const pdf = new jsPDF({ unit: 'px', format: [canvasWidth, canvasHeight] }); // 方案B:按比例缩放到A4页面(避免页面过大) const a4PxWidth = 595.28; // 72dpi下A4的宽度(像素) const scaleRatio = a4PxWidth / canvasWidth; const targetPdfHeight = canvasHeight * scaleRatio; const pdf = new jsPDF({ unit: 'px', format: [a4PxWidth, targetPdfHeight] });
3. 添加图像时严格保持宽高比
调用addImage的时候,一定要用计算好的等比例尺寸,别硬套固定的页面大小:
// 正确姿势:用Canvas真实尺寸或等比例缩放后的尺寸 pdf.addImage( mapCanvas, 'PNG', 0, // x坐标 0, // y坐标 canvasWidth, // 图像宽度(和PDF单位一致) canvasHeight // 图像高度(严格按比例) ); // 错误示例:强制A4尺寸,直接拉伸变形 // pdf.addImage(mapCanvas, 'PNG', 0, 0, 595, 842);
4. 可选:处理地图视图偏移
如果导出前地图有平移、缩放,可能导致导出内容不全或比例异常。可以先临时重置视图到全图范围,导出后再恢复:
// 保存当前视图状态 const view = map.getView(); const originalCenter = view.getCenter(); const originalZoom = view.getZoom(); // 重置视图到图层全范围 view.fit(map.getLayerGroup().getExtent()); // 等待视图渲染完成再导出(根据项目调整延迟时间) setTimeout(() => { // 这里执行你的PDF导出逻辑... // 恢复原视图 view.setCenter(originalCenter); view.setZoom(originalZoom); }, 500);
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

