html转pdf

250 阅读1分钟

`---

主题使用方法:github.com/xitu/juejin…

theme: juejin highlight: juejin ---`

只有一页的

export const html2pdf = function (
  title = '文档',
  selector = '#pdfDom',
  isUpload,
) {
  return new Promise((resolve, reject) => {
    html2Canvas(document.querySelector(selector), {
    }).then(function (canvas) {
      const loading = Loading.service({
        lock: true,
        text: '加载中……',
        background: 'rgba(0, 0, 0, 0.7)',
      });
      const contentWidth = canvas.width;
      const contentHeight = canvas.height;
      const pageHeight = (contentWidth / 592.28) * 841.89;
      let leftHeight = contentHeight;
      let position = 0;
      const imgWidth = 595.28;
      const imgHeight = (592.28 / contentWidth) * contentHeight;
      const pageData = canvas.toDataURL('image/jpeg', 1.0);
      const PDF = new JsPDF('', 'pt', 'a4');
      if (leftHeight < pageHeight) {
        PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
      } else {
        while (leftHeight > 0) {
          PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
          leftHeight -= pageHeight;
          position -= 841.89;
          if (leftHeight > 0) {
            PDF.addPage();
          }
        }
      }
      if (isUpload) {
        const pdfData = PDF.output('datauristring'); //获取base64Pdf
        const file = dataURLtoFile(pdfData, title);
        resolve(file);
        loading.close();
      } else {
        PDF.save(`${title}.pdf`);
        loading.close();
      }
    });
  });
};`

多页 分页内容会被截断处理

export function downlaodReport(
  title = '文档',
  selector = '#pdfDom',
  isUpload,
  isDownload,
) {
  return new Promise((resolve, reject) => {
    html2Canvas(document.querySelector(selector), {
      useCORS: true,
      dpi: 120, // 图片清晰度问题
      background: '#FFFFFF', //如果指定的div没有设置背景色会默认成黑色,这里是个坑
    }).then(canvas => {
      const loading = Loading.service({
        lock: true,
        text: '加载中……',
        background: 'rgba(0, 0, 0, 0.7)',
      });
      //未生成pdf的html页面高度
      let leftHeight = canvas.height;

      const a4Width = 595.28;
      const a4Height = 841.89; //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
      //一页pdf显示html页面生成的canvas高度;
      const a4HeightRef = Math.floor((canvas.width / a4Width) * a4Height);

      //pdf页面偏移
      let position = 0;

      const pageData = canvas.toDataURL('image/jpeg', 1.0);

      const pdf = new JsPDF('p', 'pt', 'a4'); //A4纸,纵向
      let index = 1,
        canvas1 = document.createElement('canvas'),
        height;
      pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen');

      const pdfName = title;
      function createImpl(canvas) {
        if (leftHeight > 0) {
          index++;

          let checkCount = 0;
          if (leftHeight > a4HeightRef) {
            let i = position + a4HeightRef;
            for (i = position + a4HeightRef; i >= position; i--) {
              let isWrite = true;
              for (let j = 0; j < canvas.width; j++) {
                const c = canvas.getContext('2d').getImageData(j, i, 1, 1).data;

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

          canvas1.width = canvas.width;
          canvas1.height = height;

          const ctx = canvas1.getContext('2d');
          ctx.drawImage(
            canvas,
            0,
            position,
            canvas.width,
            height,
            0,
            0,
            canvas.width,
            height,
          );

          const pageHeight = Math.round((a4Width / canvas.width) * height);
          if (position !== 0) {
            pdf.addPage();
          }
          pdf.addImage(
            canvas1.toDataURL('image/jpeg', 1.0),
            'JPEG',
            10,
            10,
            a4Width,
            (a4Width / canvas1.width) * height,
          );
          leftHeight -= height;
          position += height;
          if (leftHeight > 0) {
            setTimeout(createImpl, 500, canvas);
          } else if (isUpload) {
            const pdfData = pdf.output('datauristring'); //获取base64Pdf
            const file = dataURLtoFile(pdfData, pdfName);
            resolve(file);
            loading.close();
            if (isDownload) {
              pdf.save(`${pdfName}.pdf`);
              loading.close();
            }
          } else {
            pdf.save(`${pdfName}.pdf`);
            loading.close();
          }
        }
      }

      //当内容未超过pdf一页显示的范围,无需分页
      if (leftHeight < a4HeightRef) {
        pdf.addImage(
          pageData,
          'JPEG',
          0,
          0,
          a4Width,
          (a4Width / canvas.width) * leftHeight,
        );
        if (isUpload) {
          const pdfData = pdf.output('datauristring'); //获取base64Pdf
          const file = dataURLtoFile(pdfData, pdfName);
          resolve(file);
          if (isDownload) {
            pdf.save(`${pdfName}.pdf`);
            loading.close();
          }
        } else {
          pdf.save(`${pdfName}.pdf`);
          loading.close();
        }
      } else {
        try {
          pdf.deletePage(0);
          setTimeout(createImpl, 500, canvas);
        } catch (err) {}
      }
    });
  });
}

内容放置一页 避免截断

// 将所有内容放置一页,避免内容截断问题
export function downloadOnePage(
  title = '文档',
  selector = '#pdfDom',
  isUpload,
  isDownload,
) {
  return new Promise((resolve, reject) => {
    const loading = Loading.service({
      lock: true,
      text: '加载中……',
      background: 'rgba(0, 0, 0, 0.7)',
    });
    html2Canvas(document.querySelector(selector), {
      // allowTaint: true,
      useCORS: true,
      dpi: 120, // 图片清晰度问题
      background: '#FFFFFF',
      // scale: 2, // 提升画面质量,但是会增加文件大小
    }).then(canvas => {
      // 得到canvas画布的单位是px 像素单位
      const contentWidth = canvas.width;
      const contentHeight = canvas.height;
      // 将canvas转为base64图片
      const pageData = canvas.toDataURL('image/jpeg', 1.0);

      // 设置pdf的尺寸,pdf要使用pt单位 已知 1pt/1px = 0.75   pt = (px/scale)* 0.75
      // 2为上面的scale 缩放了2倍
      const pdfX = ((contentWidth + 10) / 2) * 0.75;
      const pdfY = ((contentHeight + 500) / 2) * 0.75; // 500为底部留白

      // 设置内容图片的尺寸,img是pt单位
      const imgX = pdfX;
      const imgY = (contentHeight / 2) * 0.75; //内容图片这里不需要留白的距离

      // 初始化jspdf 第一个参数方向:默认''时为纵向,第二个参数设置pdf内容图片使用的长度单位为pt,第三个参数为PDF的大小,单位是pt
      const PDF = new JsPDF('', 'pt', [pdfX, pdfY]);

      // 将内容图片添加到pdf中,因为内容宽高和pdf宽高一样,就只需要一页,位置就是 0,0
      PDF.addImage(pageData, 'jpeg', 0, 0, imgX, imgY);
      // PDF.save(`${title}.pdf`);

      if (isUpload) {
        const pdfData = PDF.output('datauristring'); //获取base64Pdf
        const file = dataURLtoFile(pdfData, title);
        resolve(file);
        loading.close();
        if (isDownload) {
          PDF.save(`${title}.pdf`);
          loading.close();
        }
      } else {
        PDF.save(`${title}.pdf`);
        loading.close();
      }
    });
  });
}

有跨域图片时候需要将允许污染去掉 可在图片url添加时间戳 将图片属性crossOrigin 设置为 "Anonymous";