关于HTML导出word报告的问题(地图、图表)
前提
产品上一个需求,就是做一个分析报告,报告里包括生成的(ol)地图,(echarts)图表,(table)表格和问题描述等。。
用到的组件:
"ol": "^6.8.1",
"ol-ext": "^3.2.6",
"html-docx-js": "^0.3.1",
"html2canvas": "^1.3.2",
"element-ui": "^2.15.6",
问题
- 其中问题最少的就是图表了,基本上只要能把canvas转图片就好了
- table的问题就是使用组件的话导出会有大小无法控制的问题,一直都是以表格内容的大小撑开,最后还是先用原生的table去写一个,用Css去控制大小和样式,理论上应该用组件也能控制width:100%,但是就是不生效。。
- 最后就是ol地图的问题了,ol的问题是导出的地图包括三种点图、热力图和聚合图,导出的地图也是几种的任意组合,总的来说由于它们是分别的图层叠加,就说会有底图层,绘制的面或线层,点图标记层,热力图分布层,聚合图分布层,如果直接用Canvas去获取转图片,就会出现很多张分裂的图层图片,可能还会有底层地图块,点标记图片等。
解决
/* 转换图片为 base64 (todo: 有可能因跨域报错) */
convertImagesToBase64(contentDocument) {
// 找到所有的图片
let imgs = contentDocument.querySelectorAll("img");
// 图片转换用
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
imgs.forEach((img, i) => {
if (img.src.startsWith("data:image")) return;
//过滤多余的地图底层瓦片图片和标记图片,如你的报告里有小图片,慎用
if(img.width<200){
return
}
// img表现尺寸
let realWidth = parseInt(img.width) - 100;
let realHeight = parseInt(img.height);
// 清空画布并调整为 img 的大小
ctx.clearRect(0, 0, canvas.width, canvas.height);
canvas.width = realWidth;
canvas.height = realHeight;
// 画图片到画布
ctx.drawImage(
img,
0,
0,
img.width,
img.height,
0,
0,
realWidth,
realHeight
);
// ctx.drawImage(img, 0, 0, 400, 200);
// 画布转为 base64
let dataURL = canvas.toDataURL();
img.setAttribute("src", dataURL);
});
canvas.remove();
},
/* 转换canvas为img */
convertChartsToBase64(contentDocument) {
// 找到所有的地图 (ol)进行图层合并转出
//.ra_map是自行封装的地图组件标记样式,需要更换
let canvases = contentDocument.querySelectorAll(".ra_map");
canvases.forEach((item,i)=>{
let target = item.getAttribute('id')
//获取所有地图组件下的图层,进行合并
let list = document.getElementById(target).querySelectorAll("canvas")
let imgDom = document.createElement('img')
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
//保持原有的显示大小,否则可能会变化
canvas.width = 706;
canvas.height = 500;
if(list.length){
let image = new Image();
image.src = list[0].toDataURL("image/png");
// image.crossOrigin = 'Anonymous';
list.forEach((res,idx)=>{
ctx.drawImage(image , 0 , 0 , 706 , 500);
let img = new Image();
img.src = res.toDataURL("image/png");
// img.crossOrigin = 'Anonymous';
img.onload = function(){
ctx.drawImage(img , 0 , 0 , 706 , 500);
let base64 = canvas.toDataURL("image/png"); //"image/png" 这里注意一下
imgDom.setAttribute('src' , base64);
}
})
imgDom.style.width = '100%'
//width的设置为导出成word后的图片大小设定,1px为0.04cm,不设定为原尺寸
imgDom.width = parseInt(canvas.style.width.replace('px','')) - 86 || 620;
item.parentNode.replaceChild(imgDom, item);
}
canvas.remove();
})
// 找到所有的图表 (echart)
let charts = contentDocument.querySelectorAll("canvas");
//遍历图表,转换为 base64 静态图片
charts.forEach((chart, i) => {
let img = new Image();
img.src = chart.toDataURL("image/png");
img.style.width = '100%'
img.width = parseInt(chart.style.width.replace('px','')) - 86 || 620;
chart.parentNode.replaceChild(img, chart);
});
},
ol也有它自己的导出图片方法
参考:导出图片
获取地图层的方式是:querySelectorAll(’.ol-layer canvas, canvas.ol-layer’)
原项目还有一个地图导出问题
使用的html2canvas导出地图图片。问题:
1.它无法保存热力图
2.导出图片偏移,无法校准,查了一下是跟样式translate有关,但是ol里面都是这种样式,就算用offset和x,y去重置0都解决不了,还是官方导出较为实在
html2canvas(document.getElementById(this.mapOption.target), {useCORS: true}).then(
(canvas) => {
canvas.toBlob(function (blob) {
saveAs(blob, 'map.png');
});
});
总结
希望本记录能帮助遇到同样问题的你!