纯前端--原生js将html页面变成pdf文件(html2canvas+jsPDF)
admin 阅读: 2024-03-31
后台-插件-广告管理-内容页头部广告(手机) |
一、html2canvas – 将dom变成图片:
下载或者安装html2canvas:官网
1、将文档放在本地,用原生js进行引用和使用。
① 新建一个名为 html2canvas.min.js 的文件,并且将线上的内容进行复制。
② 引入 js 文件:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
2、使用 npm 进行安装使用:
待续。。。
二、jsPDF – 将图片变成pdf:
下载或者安装jsPDF :
- github
- 中文网站
- CDN
- Jspdf.es.js:ES 2015 模块格式。
- Jspdf.umd.js:UMD模块格式,用于 AMD 或脚本标签加载。
- Jspdf.polyfills.js:Internet Explorer等旧浏览器所需的兼容文件。
1、将文档放在本地,用原生js进行引用和使用。
① 新建一个名为 jsPDF.min.js 的文件,并且将线上(我找到的都不能用)或者资源 的内容进行复制。
② 引入 js 文件:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
2、使用 npm 进行安装使用:
待续。。。
三、普通使用(html2canvas+jsPDF):
1、 layui 或者原生js使用:
// html: <div id="box"> <button id="btn">下载为pdf</button> 内容.... </div> // js: // layui引入: layui.define(['html2canvas', 'jsPDF'], function (exports) { var html2canvas = layui.html2canvas; // 引入html转图片 var jsPDF = layui.jsPDF; // 引入图片转pdf // 初始化 var init = function() { // 点击下载按钮 document.getElementById("btn").onclick=function(){ html2canvas(document.getElementById("box"),{ allowTaint: false, // 是否允许跨域图像。会污染画布,导致无法使用canvas.toDataURL 方法 backgroundColor: '#fff', // 画布背景色(如果未在DOM中指定)。设置null为透明 useCORS: true, // 是否尝试使用CORS从服务器加载图像 dpi: 192, // 导出pdf清晰度 scale: window.devicePixelRatio * 3, // 用于渲染的比例。默认为浏览器设备像素比率。 }).then(canvas => { // html生成图片的数据 var imageData = canvas.toDataURL('image/jpeg', 1.0); // 原本的html页面的宽高 const canvasWidth = canvas.width; const canvasHeight = canvas.height; // 当分辨率是72像素/英寸时,A4纸像素长宽分别是842×595 var a4Width = 595; // A4 宽度 var a4Height = (595 / canvasWidth) * canvasHeight; // A4总高度 // 生成pdf的一页显示html的高度 let pageHeight = canvasWidth / 595 * 842; // 未生成pdf的html页面高度,最初是整体的高度 let restHeight = canvasHeight; // 页面上下偏移的大小 var position = 0; /** * 参数1:方向:l:横向 p:纵向 * 参数2:单位:"pt"、"mm"、"cm"、"m"、"in"、"px" * 参数3:格式:默认为a4 */ var pdf = new jsPDF('p', 'pt', 'a4'); // 当内容未超过pdf一页显示的范围,无需分页 if (restHeight < pageHeight) { /** * 将图像添加到PDF中 * 参数1:图片的url * 参数2:图片的格式 * 参数3:图片上下偏移的大小 * 参数4:原始宽度 * 参数5:原始高度 */ pdf.addImage(imageData, 'JPEG', 0, position, a4Width, a4Height ); } else { while(restHeight > 0) { pdf.addImage(imageData, 'JPEG',0, position, a4Width, a4Height) restHeight -= pageHeight; position -= 842; if(restHeight > 0) { // 在PDF文档中添加新页面 pdf.addPage(); } } } // 保存为pdf格式的文件 pdf.save('生成的pdf文件.pdf') }) } } var Class = { init: function (options) { init(); return this; } } exports('XXX', Class); )}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
2、 vue/react 框架进行使用:
待续。。。
四、模块分割(html2canvas+jsPDF – 文字会截断,除了让后端做,没找到别的解决办法,感觉后端的插件比前端的更好用…):
参考链接:https://blog.csdn.net/qq_32244819/article/details/109678481
具体代码:
// 点击下载按钮 document.getElementById("btn").onclick=function(){ outPutPdfFn() } // 导出方法 var outPutPdfFn = function() { const A4_WIDTH = 592.28; // A4纸的宽 const A4_HEIGHT = 841.89; // A4纸的高 console.log('正在导出pdf,请稍候...'); let target = document.getElementById('box'); // 需要打印的页面的dom let pageHeight = target.scrollWidth / A4_WIDTH * A4_HEIGHT; // 根据比例换算一页的高度 // 获取分割的dom,即class类名为splitItem的dom let splitItemAll = document.getElementsByClassName('splitItem'); // 进行分割操作,当分块的内容超出a4纸的高度,则在这个块之前插入一个空白的块,将原有的块下移进行分割 for (let i = 0; i < splitItemAll.length; i++) { // 计算当前模块需要分成几部分 let modulesNum = Math.ceil((splitItemAll[i].offsetTop + splitItemAll[i].offsetHeight) / pageHeight); if (isSplit(splitItemAll, i, modulesNum * pageHeight)) { let divParent = splitItemAll[i].parentNode; // 获取当前需要分割块的父节点 let newNode = document.createElement('div'); newNode.className = 'emptyDiv'; newNode.style.background = '#ffffff'; // 计算需要插入块的高度 let _H = modulesNum * pageHeight - (splitItemAll[i].offsetTop + splitItemAll[i].offsetHeight); newNode.style.height = _H + 'px'; newNode.style.width = '100%'; let nextDom = splitItemAll[i].nextSibling; // 获取当前需要分割块的下一个兄弟节点 // 判断兄弟节点是否存在 console.log(nextDom); if (nextDom) { // 存在则将新节点插入到下一个兄弟节点的前面 divParent.insertBefore(newNode, nextDom); } else { // 不存在则直接添加 divParent.appendChild(newNode); } } } getPdf('导出pdf', 'box') } /** * 计算当前内容是否跨越了a4大小,以此分割 * @params nodes 拿到的所有需要分割的dom * @params index 当前需要分割内容的索引 * @params pageHeight A4纸的高度 */ var isSplit = function(nodes, index, pageHeight) { // 当前需要分割的内容:内容高度+内容距离页面定位父元素(/body)的高度 < 页面的高度 // 当前需要分割的内容的下一个兄弟节点:内容高度+内容距离页面定位父元素(/body)的高度 > 页面的高度 if (nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight) { return true; } return false; } // 导出pdf var getPdf = function(title, dom) { html2canvas(document.getElementById(dom),{ allowTaint: false, // 是否允许跨域图像。会污染画布,导致无法使用canvas.toDataURL 方法 backgroundColor: '#fff', // 画布背景色(如果未在DOM中指定)。设置null为透明 useCORS: true, // 是否尝试使用CORS从服务器加载图像 dpi: 192, // 导出pdf清晰度 scale: window.devicePixelRatio * 3 // 用于渲染的比例。默认为浏览器设备像素比率。增加清晰度 }).then(canvas => { // html生成图片的数据 var imageData = canvas.toDataURL('image/jpeg', 1.0); // 原本的html页面的宽高 const canvasWidth = canvas.width; const canvasHeight = canvas.height; // 当分辨率是72像素/英寸时,A4纸像素长宽分别是842×595 var a4Width = 592.28; // A4 宽度 var a4Height = (592.28 / canvasWidth) * canvasHeight; // A4总高度 // 生成pdf的一页显示html的高度 let pageHeight = canvasWidth / 592.28 * 841.89; // 未生成pdf的html页面高度,最初是整体的高度 let restHeight = canvasHeight; // 页面上下偏移的大小 var position = 0; /** * 参数1:方向:l:横向 p:纵向 * 参数2:单位:"pt"、"mm"、"cm"、"m"、"in"、"px" * 参数3:格式:默认为a4 */ var pdf = new jsPDF('p', 'pt', 'a4'); // 当内容未超过pdf一页显示的范围,无需分页 if (restHeight < pageHeight) { /** * 将图像添加到PDF中 * 参数1:图片的url * 参数2:图片的格式 * 参数3:图片上下偏移的大小 * 参数4:原始宽度 * 参数5:原始高度 */ pdf.addImage(imageData, 'JPEG', 0, 0, position, a4Height ); } else { while(restHeight > 0) { pdf.addImage(imageData, 'JPEG',0, position, a4Width, a4Height) restHeight -= pageHeight; position -= 841.89; if(restHeight > 0) { // 在PDF文档中添加新页面 pdf.addPage(); } } } // 保存为pdf格式的文件 pdf.save(`${title}.pdf`) }) }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
五、echarts图表模糊的解决办法:
// 方法一:初始化echarts的时候,添加清晰度配置 devicePixelRatio echarts.init(chartDom, null, { devicePixelRatio: window.devicePixelRatio * 3 }); // 方法二:使用svg渲染,这个效果更好,就是需要调整grid,不然图表不完整 // echarts.init(chartDom, null, { renderer: "svg" })- 1
- 2
- 3
- 4
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |