|
所见即所得——HTML转图片组件开发
161 前言在我们日常开发中一定会遇到"所见即所得"的需求,如导出查询表格中的内容为 Excel 表格——《前端导出 Excel,让后端刮目相看》(https://juejin.cn/post/7030291455243452429)、通过后台网页配置实现配置预览页与实际页面展示的统一——《从零开发一款可视化大屏制作平台》(https://juejin.cn/post/6937257727106220040)。今天我们也来实现一个"所见即所得"的需求:将用户所见网页提取为图片。方案 1:最短步骤实现结果第一个想到的方案就是通过浏览器自带的网页另存为图片去实现。但这种方法显然是不可行的。第一需要提示用户操作进行繁琐的操作,第二无法达到局部提取为图片的效果。方案 2:达成初步可行方案通过调研发现,可以使用 html2canvas(http://html2canvas.hertzen.com/) 将网页先转换为 canvas 数据。再将其转换为图片的方法,最终实现我们想要的功能。引入 html2canvascnpm install --save html2canvasHTML
名称:
年龄:
班级: 班级1 班级2 保存为图片 JS// 点击保存为 Canvas onSaveCanvas(){ // 这里的类名要与点击事件里的一样 const canvas = document.querySelector('#screenshot-box'); let that = this; html2canvas(canvas,{scale:2,logging:false,useCORS:true}).then(function(canvas) { const type = 'png'; let imgData = canvas.toDataURL(type); // 图片格式处理 let _fixType = function(type) { type = type.toLowerCase().replace(/jpg/i, 'jpeg'); let r = type.match(/png|jpeg|bmp|gif/)[0]; return 'image/' + r; }; imgData = imgData.replace(_fixType(type),'image/octet-stream'); let filename = "htmlImg" + '.' + type; // 保存为文件 // 以bolb文件下载 that.downFileToLocal(filename,that.convertBase64ToBlob(imgData)) }); },如此我们便实现了初步的功能当然,我们也可以设置一个预览图片来预览我们将要导出的图片HTMLJSthis.previewPic = URL.createObjectURL(that.convertBase64ToBlob(imgData));展示效果将方案进行拓展并升级需求止步于此,但秉承着"将事情做的更好"的我们岂能止步于此。实现 HTML 导出为 Word我们需要通过 html-docx 来实现导出为 Word(导出 Word 目前只支持原生 HTML + CSS)。引入 html-docxcnpm install --save html-docx-jsHTML 姓名 年龄 贾维斯 2 导出为wordJSonWordExport(){ var contentHtml = document.getElementById("export-word").innerHTML; const cssHTML = `table { width: 200px; border: 1px solid #ccc; color:red; }` var content = ` ${contentHtml} ` var converted = htmlDocx.asBlob(content,{orientation:"landscape"}); this.downFileToLocal('word文件名.docx',converted) }展示效果如此我们便实现了导出 HTML 为 Word。实现 HTML 导出为 PDF目前市面上 HTML 导出 PDF 的实现方式有多种,如 jsPDF (https://github.com/parallax/jsPDF)、iText (https://blog.csdn.net/weixin_43897590/article/details/124729389)、wkhtmltopdf (https://github.com/wkhtmltopdf/wkhtmltopdf) 等。在不同情况下我们应该使用不同的解决方案:方案优点缺点分页图片表格链接中文特殊字符jsPDF1、整个过程在客户端执行(不需要服务器参与),调用简单1、生成的 pdf 为图片形式,且内容失真支持支持支持不支持支持支持iText1、功能基本可以实现,比较灵活 2、生成 pdf 质量较高1、对 html 标签严格,少一个结束标签就会报错;2、后端实现复杂,服务器需要安装字体;3、图片渲染比较复杂支持支持支持支持支持支持wkhtmltopdf1、调用方式简单;2、生成pdf质量较高1、服务器需要安装 wkhtmltopdf 环境;2、根据网址生成 pdf,对于有权限控制的页面需要在拦截器进行处理支持支持支持支持支持支持今天我们使用在客户端执行(不需要服务器参与)的方式——jsPDF。导入 jsPDFnpm install --save jspdfHTML 导出为PDFJS// 导出为 DF onPDFExport(){ const canvas = document.querySelector('#screenshot-box'); html2canvas(canvas).then(function(canvas) { let contentWidth = canvas.width; let contentHeight = canvas.height; //一页 pdf 显示 html 页面生成的 canvas 高度; let pageHeight = contentWidth / 592.28 * 841.89; //未生成 pdf 的 html 页面高度 let leftHeight = contentHeight; //页面偏移 let position = 0; //a4 纸的尺寸[595.28,841.89],html 页面生成的 canvas 在 pdf 中图片的宽高 let imgWidth = 595.28; let imgHeight = 592.28/contentWidth * contentHeight; let pageData = canvas.toDataURL('image/jpeg', 1.0); let pdf = new jsPDF('', 'pt', 'a4'); //有两个高度需要区分,一个是 html 页面的实际高度,和生成 pdf 的页面高度(841.89) //当内容未超过 pdf 一页显示的范围,无需分页 if (leftHeight 0) { pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) leftHeight -= pageHeight; position -= 841.89; //避免添加空白页 if(leftHeight > 0) { pdf.addPage(); } } } pdf.save('content.pdf'); }) }展示效果如此我们便实现了导出 HTML 为 PDF。将功能封装为组件实现一次 HTML 导出图片需要写的代码太多,很多参数也需要按需定制。是否能够将其封装成组件呢?我们可以通过 Vue 的插槽 (https://v2.cn.vuejs.org/v2/api/#v-slot) 将我们导出的内容进行插入完整组件 组件导出为图片
|
|