一、需求背景
最近开发时,有遇到这么一个需求,要将一个有大量图表/文字/图片的页面导出为pdf(该页面的图表以及文字、图片是可动态配置的),目前主流的方式都是用htmlCanvas插件做的,我们一向的原则是少用插件多用原生,所以最后和产品沟通,导出为图片,因为图片可以用原生实现,并且默认单页,效果也非常好。
二、实现方式
实现方式参考了张鑫旭老师的一篇文章
借助SVG forginObject实现DOM转图片
,在此基础上做了一些细节的调整。
这种方式基本的原理,就是将dom转换成xml结构,然后放在<forginObject>标签内,借助svg的处理能力将dom结构转换成svg标签,然后将svg标签作为图片的base64地址,最后用a标签实现下载。整个过程无需插件或者服务器支持,纯原生,浏览器兼容性也很好,生成速度,按照我的经验,2S内可以完成,可以说算还行的吧。下面贴一下具体的代码以及一些要注意的细节
特别提示:dom内的svg标签无需单独处理
三、实现细节
封装一个函数用于实现dom转图片
function getImgByDom(params) {
const { target } = params;
//克隆一份dom节点
const cloneDom = target.cloneNode(true);
cloneDom.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
const width = target.offsetWidth;
const height = target.offsetHeight;
//转成base64位地址
const xmlContent = (xmlContent = `data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"
width="${width}" height="${height}"><foreignObject x="0" y="0" width="100%" height="100%">
${new XMLSerializer().serializeToString(cloneDom)}
</foreignObject></svg>`);
//处理部分特殊字符
return xmlContent.replace(/\n/g, "").replace(/\t/g, "").replace(/#/g, "%23");
}
下面是一些实现的细节
1.处理img元素
上面的方法只能处理普通的标签,img标签通常情况下地址不是base64的,所以我们要先把img标签的地址转换成base64,在这里我们可以借助canvas实现。
封装一个方法获取图片的base64地址
/**
*获取img元素的bse64地址
* @param {HTMLElement} imgEle img元素
*/
function getBse64ByImg(imgEle) {
const canvas = window.document.createElement("canvas");
canvas.width = imgEle.width;
版权声明:本文为weixin_42733155原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。