pdf.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // 创建 pdf.js
  2. // 引入依赖
  3. import Vue from 'vue'
  4. import html2canvas from 'html2canvas'
  5. // #ifdef H5
  6. import JsPDF from 'jspdf'
  7. // #endif
  8. const PDF = {}
  9. PDF.install = function (Vue, options) {
  10. /**
  11. * targetDom: 需要打印的dom对象
  12. * name:pdf的名字
  13. * callback: 回调函数
  14. */
  15. Vue.prototype.$createPdf = function (targetDom, name, callback) {
  16. // console.log(window.devicePixelRatio * 4)
  17. // a4纸的尺寸[592.28,841.89]
  18. uni.showLoading({
  19. title: '导出中'
  20. })
  21. const A4_WIDTH = 592.28
  22. const A4_HEIGHT = 841.89
  23. // 每页pdf 相对于A4纸张的页面所对应的高度
  24. let pageHeight = targetDom.scrollWidth / A4_WIDTH * A4_HEIGHT
  25. //将dom对象复制一份出来,我们要对dom对象的大小进行调整,不能影响原页面dom对象的样式
  26. let cloneDom = targetDom.cloneNode(true)
  27. cloneDom.style.width = targetDom.scrollWidth + 'px'
  28. cloneDom.style.background = '#FFFFFF'
  29. // cloneDom.style.display = 'none'
  30. document.body.appendChild(cloneDom)
  31. //这里划重点,将页面中的预计生成一页的div设置一个单独的class,然后根据class获取到所有的节点,即可大致知道将要生成多少页的PDF
  32. let pages = cloneDom.childNodes
  33. //遍历一次这些节点
  34. for (let i = 0; i < pages.length; i++) {
  35. //判断每个页面的节点对象,高度是否大于或小于实际的PDF的高度,如果大于PDF每页的高度,那这个节点最少也要生成2页的PDF,切不能影响下面的节点的,用节点对象的高度/PDF每页的高度,向上取整获取到倍数,然后设置该节点的高度为:PDF每页的高度*倍数,如果节点高度小于PDF每页的高度,直接将该节点高度设置成PDF每页的高度即可
  36. if (pages[i].offsetHeight > pageHeight) {
  37. let num = Math.ceil(pages[i].offsetHeight / pageHeight)
  38. pages[i].style.height = pageHeight * num + 'px'
  39. } else {
  40. // pages[i].style.height = pageHeight + 'px'
  41. }
  42. //页面中每页的div之间有间隔,将这个间隔去掉
  43. // pages[i].style.marginBottom = 0 + 'px'
  44. }
  45. html2canvas(cloneDom, {
  46. scale: 4, // 提升画面质量,但是会增加文件大小
  47. useCORS: true, // 允许跨域图片 当图片是链接地址时,需加该属性,否组无法显示图片
  48. imageTimeout: 0, // 图片加载延迟,默认延迟为0,单位毫秒
  49. height: cloneDom.scrollHeight, // canvas的高度设定,这里的宽高要用复制出来的dom对象的宽高,不能用原dom对象,因为我们已经将dom的高度整体拉高了
  50. width: cloneDom.scrollWidth, // canvas的宽度设定
  51. windowWidth: document.body.scrollWidth,
  52. windowHeight: document.body.scrollHeight,
  53. dpi: 172, // 将分辨率提高到特定的DPI
  54. logging: false,
  55. allowTaint: false,
  56. }).then(canvas => {
  57. document.body.removeChild(cloneDom) // 移除节点否者会多出一份
  58. const _this = this;
  59. //未生成pdf的html页面高度
  60. var leftHeight = canvas.height;
  61. var a4Width = 555.28 // 原A4宽 592 因为要设置边距 20 ,这里要减掉 40
  62. var a4Height = 801.89 // 原A4高 841 因为要设置边距 20 ,这里要减掉 40
  63. //一页pdf显示html页面生成的canvas高度;
  64. var a4HeightRef = Math.floor(canvas.width / a4Width * a4Height);
  65. //pdf页面偏移
  66. var position = 0;
  67. var pageData = canvas.toDataURL('image/jpeg', 1.0);
  68. var pdf = new JsPDF('x', 'pt', 'a4');
  69. var index = 1,
  70. canvas1 = document.createElement('canvas'),
  71. height;
  72. pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen');
  73. function createImpl(canvas) {
  74. if (leftHeight > 0) {
  75. index++;
  76. var checkCount = 0;
  77. if (leftHeight > a4HeightRef) {
  78. var i = position + a4HeightRef;
  79. for (i = position + a4HeightRef; i >= position; i--) {
  80. var isWrite = true
  81. for (var j = 0; j < canvas.width; j++) {
  82. var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data
  83. if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {
  84. isWrite = false
  85. break
  86. }
  87. }
  88. if (isWrite) {
  89. checkCount++
  90. if (checkCount >= 10) {
  91. break
  92. }
  93. } else {
  94. checkCount = 0
  95. }
  96. }
  97. height = Math.round(i - position) || Math.min(leftHeight, a4HeightRef);
  98. if (height <= 0) {
  99. height = a4HeightRef;
  100. }
  101. } else {
  102. height = leftHeight;
  103. }
  104. canvas1.width = canvas.width;
  105. canvas1.height = height;
  106. // console.log(index, 'height:', height, 'pos', position);
  107. var ctx = canvas1.getContext('2d');
  108. ctx.drawImage(canvas, 0, position, canvas.width, height, 0, 0, canvas.width, height); // 边距这里设置0,不然又黑边
  109. var pageHeight = Math.round(a4Width / canvas.width * height);
  110. // pdf.setPageSize(null, pageHeight)
  111. if (position != 0) {
  112. pdf.addPage();
  113. }
  114. // 设置 20px 边距
  115. pdf.addImage(canvas1.toDataURL('image/jpeg', 1.0), 'JPEG', 20, 20, a4Width, a4Width / canvas1.width * height);
  116. leftHeight -= height;
  117. position += height;
  118. // $('.pdfProgress').text(index + 1);
  119. // $('.pdfTotal').text(index + Math.ceil(leftHeight / a4HeightRef));
  120. if (leftHeight > 0) {
  121. //添加全屏水印
  122. const base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAArCAYAAADIWo5HAAACLUlEQVR42u2Zy2sCMRDGV9tbtVJKrQ/0JBWLvbgsaOttQQqreO5R6GHP/v+HZiEDQ9i8k33YDHyXbcxufpN8maRRFCJEiBAhQoTgRIfoh+hKNBe0G9I2GVG3om9bEl2I9rcIoE/77Cq8Myd6sn2ZSBgAr80YARhI+gOwCdGW6EB/d6R9XDUGFrsAf2Fe7Fswk1JBmzMd1DNKgI2EywQyUKYjkxFeOwwxkwgAvBJNqEa0DzaTHcn3qWrXdA/ocQD8m11ABUDfQF0fpujjI2QAeoZetdYdfOzB9HgGNEF6owM8Ec3Q8wEDgP07T6ktgNyB8YgAqGZ0b+gRsS2AtQP/iAUAHlAdsEW7TY6eFVrVNQN8A2AjlZho5R5wYjJhoqMiADy4DFWLPJMcKBhv3AYThFi4yJyrAAAfDrY/1SVQVhLDOWDowIwzSQ1TqwfA1P5CU3yJlsPY8fmjcTMgptmeIwB3aFbsLCvM2BRAFR4AZXYxuEdmn38hmjoosY0B5IonxLNhIYTNby0odMoAJJL1/k10bwpgQztZKaxb2YXFRnAUhexDHzoAUsGxu3j+awNA5+RmcxW1UCx1eQB4SyI1AaBrbiMEYGrwexgYBlgrgGtU/ZUY3AlGhgByTvV5MQGgW1SomqBOUWLiATy1wgNsABQz51PzWHxTALzWAW0F0EM+MKPmnLj6x0lbAPDuC5zfNPsCcChZ25DZd4VBJCW7wrRp1+whQoQIESJEg+IPRa38G55TPkQAAAAASUVORK5CYII='
  123. for (let i = 0; i < 6; i++) {
  124. for (let j = 0; j < 5; j++) {
  125. const left = (j * 120) + 20;
  126. // pdf.addImage(base64,'JPEG', left, i*150, 20, 30); // 关掉水印
  127. }
  128. }
  129. setTimeout(createImpl, 500, canvas);
  130. } else {
  131. pdf.save(name + '.pdf');
  132. uni.hideLoading()
  133. }
  134. }
  135. }
  136. //当内容未超过pdf一页显示的范围,无需分页
  137. if (leftHeight < a4HeightRef) {
  138. pdf.addImage(pageData, 'JPEG', 20, 20, a4Width, a4Width / canvas.width * leftHeight);
  139. pdf.save('下载pdf文件名' + '.pdf')
  140. uni.hideLoading()
  141. } else {
  142. try {
  143. pdf.deletePage(0);
  144. setTimeout(createImpl, 500, canvas);
  145. } catch (err) {
  146. console.log(err);
  147. }
  148. }
  149. })
  150. }
  151. }
  152. Vue.use(PDF)
  153. export default PDF