网站制作的动画怎么做的,滕州外贸软件公司,电商平台网站开发过程,建设家装网站前言 这几天接到一个需求#xff0c;富文本编辑器的内容不仅要展示出来#xff0c;还要实现展示的内容导出pdf文件。一开始导出pdf的功能是由后端来做的#xff0c;然后发现对于宽度太大的图片#xff0c;导出的pdf文件里部分图片内容被遮盖了#xff0c;但在前端是正常显…前言 这几天接到一个需求富文本编辑器的内容不仅要展示出来还要实现展示的内容导出pdf文件。一开始导出pdf的功能是由后端来做的然后发现对于宽度太大的图片导出的pdf文件里部分图片内容被遮盖了但在前端是正常显示的只因为class样式后端无法解析。然后后端开发人员就嫌麻烦让前端来实现导出pdf的功能。。。
html2canvasV1.4.1 html2canvas 用于将 html 元素渲染成图像可以将整个页面或特定区域以图像形式进行捕获。这对于将复杂的 html 结构转换为 PDF 格式非常有用因为它可以捕获 html 中的样式、布局和图像等细节。 官网https://html2canvas.hertzen.com/
引用
npm install html2canvas1.4.1 --save
或
yarn add html2canvas1.4.1
或
script srchttps://html2canvas.hertzen.com/dist/html2canvas.js/script示例
templatediv idpdfBody stylemargin: 30px;input classtest_input typetext autocompleteoff placeholder输入框111/input classtest_btn idtestBtn typebutton value按钮//div
/templatescriptimport html2canvas from /utils/htmlToPdf/html2canvas.min;export default {name: Test,mounted() {document.getElementById(testBtn).addEventListener(click, () {this.canvasTest();});},methods: {createCanvas(dom) {html2canvas(dom, {useCORS: true, //允许跨域scale: 2, //按比例增加分辨率dpi: 200, //将分辨率提高到特定的DPI每英寸点数ignoreElements: (e) {//过滤head、body等无用的标签元素return !(e.contains(dom) || dom.contains(e) || e.tagName STYLE || e.tagName LINK);},onclone: (doc) {//Scoped CSS无法直接应用需要手动处理let inputDocArr doc.getElementsByClassName(test_input);[].forEach.call(inputDocArr, inputDoc {inputDoc.style.height 36px;inputDoc.style.lineheight 36px;inputDoc.style.width 200px;inputDoc.style.margin 20px;inputDoc.style.borderRadius 5px;inputDoc.style.border 1px solid #DCDFE6;});let btnDocArr doc.getElementsByClassName(test_btn);[].forEach.call(btnDocArr, btnDoc {btnDoc.style.color #FFFFFF;btnDoc.style.backgroundColor #1890ff;btnDoc.style.border 1px solid #1890ff;btnDoc.style.height 36px;btnDoc.style.width 80px;btnDoc.style.borderRadius 20px;});}}).then(canvas {dom.appendChild(canvas);}).finally(() {console.log(create canvas finish!);});},canvasTest() {let pdfBody document.getElementById(pdfBody);this.createCanvas(pdfBody);}}}
/scriptstyle scoped.test_input {height: 36px;line-height: 36px;width: 200px;margin: 20px;border-radius: 5px;border: 1px solid #DCDFE6;}.test_input:focus {border: 1px solid #1890ff;outline: none;}.test_btn {color: #FFFFFF;background-color: #1890ff;border: 1px solid #1890ff;height: 36px;width: 80px;border-radius: 20px;cursor: pointer;}
/style配置项 如果想隐藏某个元素不让其显示出来参考以下几种方案 1、元素标签添加 data-html2canvas-ignore 属性示例如下 2、配置项中添加 ignoreElements 属性手动过滤某个元素示例如上代码 3、配置项中添加 onclone 属性手动处理某个元素的显示与隐藏即element.style.display hidden。
jsPDFV1.5.3 jsPDF 是一个 PDF 生成库它允许你通过 JavaScript 代码创建和编辑 PDF 文档。 官网https://github.com/parallax/jsPDF
引用
npm install jsPDF1.5.3 --save
或
yarn add jsPDF1.5.3
或
script srchttps://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js/script示例
templatediv idpdfBody stylemargin: 30px;h3测试创建pdf文件/h3input idtestPdf typebutton valuepdf测试//div
/templatescriptimport jsPDF from /utils/htmlToPdf/jspdf.min;export default {name: Test,mounted() {document.getElementById(testPdf).addEventListener(click, () {this.pdfTest();});},methods: {pdfTest() {let doc new jsPDF({orientation: p,unit: mm,format: a4});doc.text(Hello world!, 10, 10);doc.save(测试.pdf);}}}
/script设置中文字体 设置英文内容是正常显示的假若内容包含中文会发现pdf文件里的内容显示乱码如下图所示
let doc new jsPDF({orientation: p, unit: mm,format: a4
});
doc.text(pdf文件测试, 10, 10);
doc.save(测试.pdf); 解决这一问题可以使用 jsPDF 提供的 setFont(font) 方法具体操作如下 1、网上下载一个支持中文的字体tff文件或者拷贝一份本地 window/font/ 路径下的字体文件ps有的字体不支持 2、从GitHub上下载jsPDF源码然后打开fontconverter目录下的fontconverter.html文件 3、选择本地的tff文件点击“Create”按钮会生成一个js文件 4、一般情况下生成的js文件直接引入页面使用会报错需要手动处理生成新的js文件 默认生成的js文件内容如下
(function (jsPDFAPI) {var font XXXXXX;var callAddFont function () {this.addFileToVFS(simfang.ttf, font);this.addFont(simfang.ttf, simfang, normal);
};
jsPDFAPI.events.push([addFonts, callAddFont])})(jsPDF.API); 然后复制一份js文件编辑内容如下格式
export function addfont(pdf) {let font XXXXXX;pdf.addFileToVFS(simfang.ttf, font);pdf.addFont(simfang.ttf, simfang, normal);
} 5、将处理好的新的js文件放入项目中然后在页面中引用并设置字体。
templatediv idpdfBody stylemargin: 30px;h3测试创建pdf文件/h3input idtestPdf typebutton valuepdf测试//div
/templatescriptimport jsPDF from /utils/htmlToPdf/jspdf.min;import {addfont} from /utils/htmlToPdf/simfang;export default {name: Test,mounted() {document.getElementById(testPdf).addEventListener(click, () {this.pdfTest();});},methods: {pdfTest() {let doc new jsPDF({orientation: p,unit: mm,format: a4});//设置中文字体addfont(doc);doc.setFont(simfang);doc.text(pdf文件测试撒大大大飒飒热通过如果还有就要让他阿松大尔特瑞特好几年是否然后他又就很尴尬发射任务给他人用不上二条天皇已经不是v堵塞惹我实在是肉体和set一年德国必须色让他管很多人把, 10, 10);doc.save(测试.pdf);}}}
/script 解决jsPDF文本不自动换行问题 中文乱码问题解决了然后新的问题又出现了文本不自动换行。解决方案参考如下 1、使用 splitTextToSize() 方法
let doc new jsPDF({orientation: p,unit: mm,format: a4
});
//设置中文字体
addfont(doc);
doc.setFont(simfang);
let con pdf文件测试撒大大大飒飒热通过如果还有就要让他阿松大尔特瑞特好几年是否然后他又就很尴尬发射任务给他人用不上二条天皇已经不是v堵塞惹我实在是肉体和set一年德国必须色让他管很多人把;
let splitCon doc.splitTextToSize(con, 190);
console.log(splitCon,splitCon)
doc.text(splitCon, 10, 10);
doc.save(测试.pdf); 2、text() 方法参数添加选项 maxWidth
let doc new jsPDF({orientation: p,unit: mm,format: a4
});
//设置中文字体
addfont(doc);
doc.setFont(simfang);
let con pdf文件测试撒大大大飒飒热通过如果还有就要让他阿松大尔特瑞特好几年是否然后他又就很尴尬发射任务给他人用不上二条天皇已经不是v堵塞惹我实在是肉体和set一年德国必须色让他管很多人把;
doc.text(con, 10, 10, {maxWidth: 190
});
doc.save(测试.pdf); jsPDF 库 API 文档地址https://artskydj.github.io/jsPDF/docs/index.html 以下是常用API仅供参考
方法说明var doc new jsPDF(orientation, unit, format, compress); 创建新文档 orientationl(横向)、p(纵向) unitpt、mm(默认)、cm、m、in or px formata3、a4(默认)、a5、letter、legal等 doc.addPage()添加一个空白页doc.setPage(pageNumber)切换到第几个页面操作doc.internal.getNumberOfPages()获取总页面数doc.text(text, x, y, options); 页面中添加文本 text文本内容 x距离页面左边的距离 y距离页面上边的距离 options可选参数配置 doc.setFont(fontName, fontStyle) 页面文本设置字体 fontName字体名称 fontStyle字体风格如加粗 doc.setFontSize(size);设置字体大小doc.setTextColor(ch1, ch2, ch3, ch4);设置文本颜色可以是颜色码或rgb值doc.addImage(imageData,format, x, y, width, height) 在 PDF 文件中添加一个图像 imageData图像的数据 format图像的类型如JPEG x、y分别表示图像左上角的坐标 width图像的宽度 height图像的高度 doc.save(filename)生成指定文件名的PDF文件
html2canvas jsPDF jsPDF 与 html2canvas 结合使用可以将 html 元素渲染成图像然后将图像插入到 jsPDF 创建的 PDF 文档中。
示例
import html2canvas from /utils/htmlToPdf/html2canvas.min;
import jsPDF from /utils/htmlToPdf/jspdf.min;
import {addfont} from /utils/htmlToPdf/simfang;
import {Loading} from element-ui;export function downloadPdf(title, dom) {let reqLoading Loading.service({fullscreen: true,text: 正在生成PDF文件......,spinner: el-icon-loading,background: rgba(0,0,0,0.5)});html2canvas(dom, {useCORS: true, //允许跨域scale: 2, //按比例增加分辨率dpi: 200, //将分辨率提高到特定的DPI每英寸点数ignoreElements: (e) {return !(e.contains(dom) || dom.contains(e) || e.tagName STYLE || e.tagName LINK);}}).then(canvas {// dom.appendChild(canvas);// 新建JsPDF对象let PDF new jsPDF({orientation: p, //参数 l横向 p纵向unit: mm, //参数测量单位ptmm, cm, m, in or pxformat: a4, //A4纸});let ctx canvas.getContext(2d);let a4w 190;let a4h 272; //A4大小210mm x 297mm四边各保留10mm的边距显示区域190x277底部留5mm的页码显示位置所以高度为272mm。let imgHeight Math.floor(a4h * canvas.width / a4w) - 2; //按A4显示比例换算一页图像的像素高度let renderedHeight 0;//计算总页数let pageCount Math.ceil(canvas.height / imgHeight);let page document.createElement(canvas);page.width canvas.width;//设置中文字体addfont(PDF);PDF.setFont(simfang);while (renderedHeight canvas.height) {page.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);//canvas转图片数据保留10mm边距PDF.addImage(page.toDataURL(image/jpeg, 1), JPEG, 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width));renderedHeight imgHeight;//计算当前页及文字let pageNumberText 第 (renderedHeight / imgHeight) 页/共 pageCount 页;//设置文字大小PDF.setFontSize(4);//设置文字颜色PDF.setTextColor(#999);//在页脚添加页码PDF.text(pageNumberText, ((a4w 8) / 2), (a4h 16));//判断是否分页如果后面还有内容添加一个空页if (renderedHeight canvas.height) {PDF.addPage();}}PDF.save(title .pdf);}).finally(() {if (reqLoading) {reqLoading.close();}});
} 常见问题
截取的图片显示空白
1、跨域问题 html2canvas 默认是不支持跨域图片的对于跨域的图片默认是无法截取进去的需要开启跨域配置
将图片转成 base64 形式设置配置项 allowTaint: true 或 useCORS: true;img 标签中添加 crossOriginanonymous;图片服务器配置 Access-Control-Allow-Origin: *
2、图片未加载完成 若图片未加载完成此时截取的也是空白解决方法就是设置延时一定事件后处理或图片添加 load 事件等图片加载完在进行截图。
3、需要截图的dom元素太多 若出现前面内容都正常截取后面内容出现空白大概率就是dom元素太多了。本人就碰到这种情况即使延时10秒后截取后面的部分还是空白没办法最后只能后端实现导出pdf功能了。。。
截图后部分css效果未正常显示
1、部分css样式 html2canvas 不支持 html2canvas 无法支持全部的css样式关于支持哪些css样式或不支持哪些css样式可以参考文档https://html2canvas.hertzen.com/features
2、scoped 作用域的css无法应用 在vue中为了避免css样式的交叉污染都会使用 scoped 作用域的css样式但是该作用域下的css样式无法在 html2canvas 中使用解决方案可以在 onclone 配置项中过滤元素手动处理样式详情可参考上述示例 其他的问题可以参考博文https://www.cnblogs.com/padding1015/p/9225517.html
总结 使用 html2canvas jsPDF 纯前端导出pdf的方式还是有很多问题的一般情况下都是后端进行文件的导出前端配合解决样式问题。 另外我看还有使用 dom-to-image 或 modern-screenshot 的不知道效果怎么样有时间可以试一下。