html页面导出加水印的pdf

记录工作实践

运用到的插件:html2Canvas,JsPDF

源码如下:

import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';
export default {
  install(Vue, options) {
    Vue.prototype.getPdf = function (title, domId) {
      // 导出之前将dom的overflow:auto设置成visible
      var sourceDom = document.querySelector('.sourceDom');
      sourceDom.style.overflow = 'visible';
      sourceDom.style.height = 'auto';
      // pdf文件名
      var title = title;
      // 不填的时候导出id是pdfDom的
      domId = domId ? domId : '#pdfDom'
      //需要转pdf的网页对象
      var container = document.querySelector(domId);
      //创建画布
      var c = document.createElement('canvas');
      // html2canvas配置项
      var opts = {
        scale: 2, //设置放大倍数 window.devicePixelRatio(根据设备像素比进行缩放)
        canvas: c,
        x: window.scrollX,
        logging: true,
        useCORS: true, //表示允许跨域资源共享,注意不能与 allowTaint 同时配置为 true
        allowTaint: false, 
        width: container.offsetWidth, // 传入节点原始宽
        height: container.offsetHeight // 传入节点原始高
      };
      //画布的宽
      c.width = container.offsetWidth * 2;
      //画布的高
      c.height = container.offsetHeight * 2;

      //将页面转换成图片
      html2Canvas(container, opts).then(function (canvas) {
       
        var contentWidth = canvas.width;
        var contentHeight = canvas.height;
        // 一页pdf显示html页面生成的canvas高度
        var pageHeight = Math.floor((contentWidth / 595.28) * 841.89);
        // 未生成pdf的html页面高度
        var leftHeight = contentHeight;
        // pdf页面偏移
        var position = 0;
        // a4纸的尺寸[595.28,,841.89],html页面生成的canvas在pdf中图片的宽高
        var imgWidth = 595.28;
        var imgHeight = (595.28 / contentWidth) * contentHeight;
        //网页的内容
        var pageData = canvas.toDataURL('image/jpeg', 1.0);
        var pdf = new JsPDF('x', 'pt', 'a4');

        var canvas1 = document.createElement('canvas');
        var height;
        pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen');

        // 创建canvas元素(水印)
        const can = document.createElement('canvas')
        can.width = 400 // 宽度
        can.height = 400 // 高度
        const cans = can.getContext('2d') // 获取canvas画布
        cans.rotate(-20 * Math.PI / 180) // 逆时针旋转π/9
        cans.font = '20px Vedana' // 设置字体
        cans.fillStyle = 'rgba(200, 200, 200, 0.3)' // 设置字体的颜色
        cans.textAlign = 'center' // 文本对齐方式
        cans.textBaseline = 'Middle' // 文本基线
        cans.fillText('XXXXXX股份有限公司', can.width/ 5, can.height/ 2) // 绘制文字
        
        // 将Canvas内容导出为DataURL格式的字符串
        var dataUrl = can.toDataURL();
        // 提取Base64编码部分,可以使用正则表达式或者split函数
        var base64Code = dataUrl.replace(/^data:image\/\w+;base64,/, '');

        // 加图片水印
        function addWaterMark(doc) {
          var totalPages = doc.internal.getNumberOfPages();
          for (let i = 1; i <= totalPages; i++) {
            doc.setPage(i);
            doc.addImage(base64Code, 'PNG', imgWidth/ 7, imgHeight/ 8, imgWidth, imgHeight);
          }
          return doc;
        }

        //判断分页的地方,在间隙时才分页
        function createYmpl(canvas) {
          if (leftHeight > 0) {
            var checkCount = 0;
            if (leftHeight > pageHeight) {
              var i = position + pageHeight;
              // 默认取pdf标准所在canvas网页高度,倒着循环,推断分页位置
              // 推断canvas.width整行是否有内容,如果有内容直接退出,
              // checkCount为0,如果整行没有内容则累加checkCount值,直到checkCount值大于等于约定分页
              for (i = position + pageHeight; i >= position; i--) {
                var isWrite = true;
                for (var j = 0; j < canvas.width; j++) {
                  var cdata = canvas.getContext('2d').getImageData(j, i, 1, 1).data;

                  if (cdata[0] !== 0xff || cdata[1] !== 0xff || cdata[2] !== 0xff) {
                    isWrite = false;
                    break;
                  }
                }
                if (isWrite) {
                  checkCount++;
                  if (checkCount >= 25) {
                    break;
                  }
                } else {
                  checkCount = 0;
                }
              }
              height = Math.round(i - position) || Math.min(leftHeight, pageHeight);

              if (height <= 0) {
                height = pageHeight;
              }
            } else {
              height = leftHeight;
            }
            canvas1.width = contentWidth;
            canvas1.height = height;
            var ctx = canvas1.getContext('2d');
            // 【重要】关闭抗锯齿   这部分也是为了强化清晰度
            ctx.mozImageSmoothingEnabled = false;
            ctx.webkitImageSmoothingEnabled = false;
            ctx.msImageSmoothingEnabled = false;
            ctx.imageSmoothingEnabled = false;


            ctx.drawImage(canvas, 0, position, contentWidth, height, 0, 0, contentWidth, height);
            console.log('canvas图片是:',can,canvas);
            if (position !== 0) {
              pdf.addPage();
            }

            pdf.addImage(
              canvas1.toDataURL('image/jpeg', 1.0),
              'JPEG',
              0,
              0,
              imgWidth,
              (imgWidth / canvas1.width) * height
            );
            leftHeight -= height;
            position += height;
            if (leftHeight > 0) {
              createYmpl(canvas);
            } else {
              // 导出pdf文件命名
              pdf = addWaterMark(pdf)
              pdf.save(title + '-' + new Date().getTime() + '.pdf');
            }
          }
        }
        // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        // 当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
          pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
          // 导出pdf文件命名
          pdf = addWaterMark(pdf)
          pdf.save(title + '-' + new Date().getTime() + '.pdf');
        } else {
          createYmpl(canvas);
        }
      });
      // 导出成功后,将dom原来的属性设置回去
      cardDom.style.overflow = 'auto';
      cardDom.style.height = '100%';
    };
  }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值