美文网首页
html2canvas + JSPDF 实现截屏下载为PDF文件

html2canvas + JSPDF 实现截屏下载为PDF文件

作者: 稻草人lxh | 来源:发表于2023-06-14 18:31 被阅读0次

    背景介绍:

    工作中产品提出需求“截图下载 并 要附加水印功能”
    首先将需求分为大致几个步骤完成:

    1. 实现截屏
    2. 下载PDF
    3. 添加水印

    截屏

    关于截屏工具首先考虑到html2canvas:


    html2canvas
      const element = document.querySelector(`#${id}`);
      const { scrollHeight, scrollWidth, offsetHeight, height } = element;
      const opts = {
        scale: 3, // 缩放比例,提高生成图片清晰度
        useCORS: true, // 允许加载跨域的图片
        allowTaint: false, // 允许图片跨域,和 useCORS 二者不可共同使用
        tainttest: true, // 检测每张图片都已经加载完成
        logging: true, // 日志开关,发布的时候记得改成 false
        height: offsetHeight,
      };
      html2canvas(element, opts).then((canvas) => {
        // 获取到所id为‘id’的元素canvas截图
      })
    

    下载PDF

    关于PDF想到的工具是jsPDF:


    jsPDF

    将canvas转成PDF并下载

        let contentWidth = canvas.width
        let contentHeight = canvas.height
        let pageHeight = contentWidth / 592.28 * 841.89 - 40
        let leftHeight = contentHeight
        let position = 20
        let imgWidth = 570
        let imgHeight = 592.28 / contentWidth * contentHeight
        let pageData = canvas.toDataURL('image/jpeg', 1.0)
        let PDF = new JsPDF('', 'pt', 'a4')
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 14, 20, imgWidth, imgHeight)
          // addWatermark(PDF, 'TEST');
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 14, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            if (leftHeight > 0) {
              PDF.addPage()
            }
          }
        }
        // 添加水印(文章下面会说到这个方法)
        PDF = addWatermark(PDF, watermarkText);
        PDF.save(title + '.pdf');
    

    添加水印

    但是添加水印功能貌似用canvas和PDF都可以实现,两者我选择了用pdf实现:
    先附代码:

    const addWatermark = (pdf, watermarkText) => {
       // 获取PDF页数,给PDF每一页添加水印
        var totalPages = pdf.internal.getNumberOfPages();
        for (let i = 1; i <= totalPages; i++) {
          pdf.setPage(i);
          addWatermarkFill(pdf, watermarkText);
        }
        return pdf;
    }
    
    const addWatermarkFill = (pdf, watermarkText) => {
      let pdfW = pdf.internal.pageSize.getWidth();
      let pdfH = pdf.internal.pageSize.getHeight();
      // 250是可以根据水印的大小调整的 可以优化为单水印的长和宽
      let xCount = pdfW / 250; 
      let yCount = pdfH / 250;
      // 下面的for循环的作用是在页面上铺满水印
      for (let y = 0; y < yCount; y++) {
        let yLocation = y * 250;
        for (let x = 0; x < xCount; x++) {
          let xLocation = x * 250;
          pdf.saveGraphicsState() // 保存图形状态
          pdf.setFontSize(40);       // 设置水印字体大小
          pdf.setTextColor(200);    // 设置水印颜色
          pdf.setGState(pdf.GState({ opacity: 0.3 })) // 设置透明度为0.3
          // 这里的SIMHEI是字体包 解决jsPDF 无法使用中文问题
          pdf.setFont('SIMHEI');
          pdf.text(watermarkText, xLocation, yLocation, { align: 'center', angle: -45});
          pdf.restoreGraphicsState()
        }
      }
      return pdf;
    }
    

    添加水印时遇到的问题:

    1. 添加水印如何铺满
      上面方法中铺满问题用for循环解决了一下,感觉这个工具应该有自己封装的铺满方法,找了很多jsPDF的相关文章都没有找到合适的,于是用for循环设置x、y坐标解决了这个问题。
    2. 水印无法使用中文
      找到的资料解释是jsPDF这玩意儿是老外做的,做的时候就没有考虑中文的情况,解决方案是在工程内添加XXXX.ttf的字体包,将格式为ttf的文件用转换工具(https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html)转成jsPDF可以用的js文件,导入到工程内用,在文件内引入,用jsPDF里的setFont方法加载一下字体包。

    相关代码:

    import "@/assets/js/SIMHEI-normal";
    
    pdf.setFont('SIMHEI');
    

    相关文章

      网友评论

          本文标题:html2canvas + JSPDF 实现截屏下载为PDF文件

          本文链接:https://www.haomeiwen.com/subject/fekkydtx.html