郑州专业网站制作的公司哪家好,wordpress 视频播放器插件,机构编制网站建设,最新购物网站建设框架jspdf html2canvas
此方案有很多的css兼容问题#xff0c;比如虚线边框、svg、页数多了内容显示不全、部分浏览器兼容问题#xff0c;光是解决这些问题就耗费了我不少岁月和精力
后面了解到新的技术方案#xff1a;
jspdf html-to-image
npm install --save html-to-i…jspdf html2canvas
此方案有很多的css兼容问题比如虚线边框、svg、页数多了内容显示不全、部分浏览器兼容问题光是解决这些问题就耗费了我不少岁月和精力
后面了解到新的技术方案
jspdf html-to-image
npm install --save html-to-image
npm install --save jspdf 原理都是一样先将html转成图片再分页生成pdf
区别在于html-to-image可以生成多种格式并且没有发现html2canvas上的css兼容问题 我这里用的是toCanvas 新建公共js文件
// 导出页面为PDF格式
import JSPDF from jspdf;
import { toCanvas } from html-to-image/**** elementName: 需要输出PDF的DOM的id*/
export const ExportSavePdf (elementName,pageTotal) {var element document.getElementById(elementName)return new Promise((resolve) {toCanvas(element,{ useCORS: true ,allowTaint:true}).then(function(canvas) {var pdf new JSPDF(p, mm, a4) // A4纸纵向var ctx canvas.getContext(2d)ctx.scale(2, 2);var a4w 210;var a4h 297 // A4大小210mm x 297mm四边各保留20mm的边距var imgHeight Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度var renderedHeight 0let pageNum 0;while (renderedHeight canvas.height ) {pageNum var page document.createElement(canvas)page.width canvas.widthpage.height Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页// 用getImageData剪裁指定区域并画到前面创建的canvas对象中page.getContext(2d).putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)pdf.addImage(page.toDataURL(image/jpeg, 1.0), JPEG, 0, 0, a4w, Math.min(a4h, a4w * page.height / page.width)) // 添加图像到页面保留10mm边距renderedHeight imgHeightif (renderedHeight canvas.height pageNum pageTotal) { pdf.addPage() } // 如果后面还有内容添加一个空页// delete page;}//这里可根据自己需求返回不同类型的数据resolve(pdf.output(blob))}).catch(function (error) {console.error(error)resolve(false)})})
}
在vue页面引入后调用
//pageTotal表示当前pdf的总页数这个可以在预览的时候计算出来
ExportSavePdf(pdfBox, _this.pageTotal).then((res) {if (res false) {this.$message.error(保存失败);return;}//获取的blob格式数据let pdfBlob res;//后面是将blob数据上传到oss这里的可以根据自己需求来getOss({})});当然也有部分兼容问题下面是我项目中遇到的问题以及我的解决方案
// 解决兼容问题在保存之前调用注意使用$nextTickcompatibilityProblem() {// 去掉所有标签中的包含“v:”的属性const elements Array.from(document.querySelector(#pdfBox).getElementsByTagName(*));for (var i 0; i elements.length; i) {var attributes elements[i].attributes;// 遍历当前标签的所有属性for (var j attributes.length - 1; j 0; j--) {var attributeName attributes[j].name;// 如果属性名称中包含 v:则移除该属性if (attributeName.includes(v:)) {elements[i].removeAttribute(attributeName);}}}// 去掉拼音a的宋体样式const songSpan Array.from(document.querySelectorAll(#pdfBox span[style*font-family:SimSun]));const aList [a, ā, á, ǎ, à];const aSpan songSpan.filter((item) aList.indexOf(item.innerText) ! -1);for (let a of aSpan) {a.style.fontFamily inherit;}// 解决图片跨域问题let imgs Array.from(document.querySelectorAll(#pdfBox img));for (let item of imgs) {item.onload function () {const protocol window.location.protocol.replace(:, );if (item.getAttribute(src).split(://).length) {const imgProtocol item.getAttribute(src).split(://)[0];const src item.getAttribute(src);if (imgProtocol ! protocol) {item.setAttribute(src, src.replace(imgProtocol, protocol));}}item.setAttribute(crossorigin, anonymous);};}},