• 使用html2canvas和jsPdf实现打印功能


    最近做项目中,️遇到过实现模版打印功能,网上也找到很多资料可以实现,有的方式可以实现分页,但是打印的A4纸上下不能留边距,后来找到一个通过剪裁的方式可以实现左右上下留边距,并且能实现分页;

    方法如下:基本思路是对获得的canvas进行切割,按A4纸大小并留边距后的比例进行剪裁,切出一页一页的内容来,再分别加到pdf中。

    DEMO:

      1 // 导出页面为PDF格式
      2 import html2canvas from "html2canvas"
      3 import JSPDF from "jspdf"
      4 export default {
      5   install(Vue, options) {
      6     /**
      7      * printId 打印区域id
      8      * isIframe 打印区域是否是iframe
      9      * childiframeIds 打印区域内包含的iframe的id
     10      */
     11     Vue.prototype.ExportSavePdf = async function (printId, isIframe, childiframeIds) {
     12       let dom;
     13       if (isIframe) {
     14           dom = document.getElementById(printId).contentWindow.document.querySelector(".flex-container")
     15       } else {
     16         dom = document.getElementById(printId);
     17       }
     18       let copyDom = dom.cloneNode(true);
     19       if (childiframeIds && childiframeIds.length > 0) {
     20         childiframeIds.forEach((fId) => {
     21           let iframeDom = document.getElementById(fId).contentWindow.document.querySelector(".flex-container");
     22           let copyIframeDom = iframeDom.cloneNode(true); // 复制iframe
     23           let copyIframeNode = copyDom.querySelector(`#${fId}`);
     24           let parentNode = copyIframeNode.parentNode;
     25           parentNode.removeChild(copyIframeNode); // 移除原有的iframe
     26           parentNode.appendChild(copyIframeDom);
     27           parentNode.style.height = iframeDom.scrollHeight + "px";
     28         })
     29       }
     30       copyDom.style.height = "auto";
     31       document.body.appendChild(copyDom);
     32       /* const [lWidth, rWidth] = [20, 20];
     33       const pageWidth = 595.28 - lWidth - rWidth // A4纸的宽高 减去左右边距
     34       const pageHeight = 841.89 */
     35       // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
     36       await html2canvas(copyDom, {
     37         logging: false,
     38          dom.scrollWidth,
     39         height: dom.scrollHeight,
     40         windowWidth: dom.scrollWidth,
     41         windowHeight: dom.scrollHeight
     42       }).then(function (canvas) {
     43         // 判断浏览器内核是否是IE
     44         if (!!window.ActiveXObject || "ActiveXObject" in window) {
     45           alert('截图打印暂不支持IE内核浏览器,请更换火狐或谷歌chrome内核浏览器,360等双核浏览器请切换至极速模式');
     46           return;
     47         }
     48 
     49         /* const contentWidth = canvas.width
     50         const contentHeight = canvas.height
     51         const pageData = canvas.toDataURL('image/jpeg/png', 1)
     52         const PDF = new JSPDF('', 'pt', 'a4') // , true
     53 
     54         // canvas图片的高
     55         const imgHeight = pageWidth / contentWidth * contentHeight // canvas的宽与PDF的宽比列一样的时候,canvas的高缩放后的值
     56         let leftHeight = imgHeight
     57         let position = 0
     58         // 如果图片的高小于A4纸的高,不分页
     59         if (leftHeight < pageHeight) {
     60           PDF.addImage(pageData, 'JPEG', lWidth, 0, pageWidth, imgHeight)
     61         } else {
     62           // 分页
     63           // let index = 0
     64           while (leftHeight > 0) {
     65             PDF.addImage(pageData, 'JPEG', lWidth, position, pageWidth, imgHeight)
     66             leftHeight = leftHeight - pageHeight
     67             position -= pageHeight
     68             if (leftHeight > 0) {
     69               PDF.addPage()
     70             }
     71           }
     72         }
     73         const link = window.URL.createObjectURL(PDF.output('blob'));
     74         window.open(link);
     75         document.body.removeChild(copyDom); */
     76         // const myWindow = window.open(link);
     77         // myWindow.print();
     78 
     79         var pdf = new JSPDF('p', 'mm', 'a4'); // A4纸,纵向
     80         var ctx = canvas.getContext('2d');
     81           var a4w = 190;
     82           var a4h = 277; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
     83           var imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4显示比例换算一页图像的像素高度
     84           var renderedHeight = 0;
     85 
     86         while (renderedHeight < canvas.height) {
     87           var page = document.createElement("canvas");
     88           page.width = canvas.width;
     89           page.height = Math.min(imgHeight, canvas.height - renderedHeight); // 可能内容不足一页
     90 
     91           // 用getImageData剪裁指定区域,并画到前面建立的canvas对象中
     92           page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight,
     93             canvas.height - renderedHeight)), 0, 0);
     94           pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height /
     95             page.width)); // 添加图像到页面,保留10mm边距
     96 
     97           renderedHeight += imgHeight;
     98           if (renderedHeight < canvas.height) { pdf.addPage(); } // 若是后面还有内容,添加一个空页
    100           page.remove();
    101         }
    102         const link = window.URL.createObjectURL(pdf.output('blob'));
    103         window.open(link);
    104         document.body.removeChild(copyDom);
    105       })
    106     }
    107   }
    108 }

    因为项目中打印的可能是iframe区域,也可以是当前窗口的body内,所以前面代码中有一些对dom的操作,

    核心代码在后半部分;

    效果如下:

  • 相关阅读:
    《Windows游戏编程技巧大师》就DirectDraw而创建DirectDraw知识笔记
    中国省城市列表(中国的性格+拼音)
    Android NDK的C++11标准支持
    DFGUI-- 标签交换 Tabstrip
    Ubuntu更改hosts档
    如何完成Nexus 9上电后激活过程
    Exception dispatching input event. use XlistView
    音乐TV2015校园招聘A第二大发行量(对中国科学院大学站)
    github basic usage in windows
    HDU 1501 Zipper(DP,DFS)
  • 原文地址:https://www.cnblogs.com/yuwenjing0727/p/15802015.html
Copyright © 2020-2023  润新知