html2canvas+jsPDF实现对指定滚动的dom元素转成pdf并分页调打印机打印

问题描述

原生的window.print()无法打印多页,也无法打印超出屏幕的元素,但是我现在需要打印的元素是滚动的,一屏显示不下,并且需要分页打印。于是只能另辟蹊径。

实现思路

  1. 使用 html2canvas 库将指定的 DOM 元素转换为 canvas 图像。
  2. 对canvas 图像按照每一页进行裁剪。
  3. 使用 jspdf 库对裁剪好的图像贴到pdf中。
  4. 调用浏览器自带的 PDF 文件打印。

代码实现

import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

// 定义打印函数
const printDomToPdf = async () => {
  const printDom = document.getElementById('printDom');
  if (!printDom) {
    console.error('未找到 id 为 printDom 的元素');
    return;
  }

  try { 
    // 将 DOM 元素转换为 canvas 
    const canvas = await html2canvas(printDom, { 
      scale: 2, // 放大比例,提高图像清晰度 
      useCORS: true, // 允许跨域请求图片 
      logging: true, // 开启日志记录 
      scrollY: 0, // 垂直滚动偏移量 
      scrollX: 0, // 水平滚动偏移量 
      windowWidth: printDom.scrollWidth, // 窗口宽度,确保捕获整个 DOM 宽度 
      windowHeight: printDom.scrollHeight // 窗口高度,确保捕获整个 DOM 高度 
    }); 
    const imgData = canvas.toDataURL('image/png'); 
    const pdf = new jsPDF('p', 'mm', 'a4'); 
    const imgProps = pdf.getImageProperties(imgData); 
    const pdfWidth = pdf.internal.pageSize.getWidth(); // 获取 PDF 页面宽度 
    const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; // 根据宽度比例计算 PDF 页面高度 

    const pageHeight = pdf.internal.pageSize.getHeight(); // 获取 PDF 单页高度 
    let position = 0; // 当前图像裁剪的起始位置 

    while (position < pdfHeight) { 
      if (position !== 0) {
        pdf.addPage(); // 如果不是第一页,添加新页面 
      } 
      // 计算当前页需要显示的图像高度,取单页高度和剩余高度的最小值 
      const sliceHeight = Math.min(pageHeight, pdfHeight - position); 
      // 计算图像在 Y 轴上的裁剪起始位置 
      const clipY = (position * imgProps.height) / pdfHeight; 
      // 计算图像在 Y 轴上的裁剪结束位置 
      const clipHeight = (sliceHeight * imgProps.height) / pdfHeight; 
      // 创建裁剪后的 canvas 
      const croppedCanvas = document.createElement('canvas'); 
      const croppedCtx = croppedCanvas.getContext('2d'); 
      croppedCanvas.width = imgProps.width; 
      croppedCanvas.height = clipHeight; 
      croppedCtx.drawImage(canvas, 0, clipY, imgProps.width, clipHeight, 0, 0, imgProps.width, clipHeight); 
      const croppedImgData = croppedCanvas.toDataURL('image/png'); 
      // 使用 9 个参数的 addImage 函数 
      pdf.addImage(croppedImgData, 'PNG', 0, 0, pdfWidth, sliceHeight, undefined, 'FAST', 0);  
      position += pageHeight; // 更新裁剪起始位置 
    } 

    // 保存并打印 PDF 
    // pdf.save('printDom.pdf'); 
    pdf.autoPrint(); 
    window.open(pdf.output('bloburl'), '_blank'); 
  } catch (error) {
    console.error('打印失败:', error);
  }
};
posted @ 2025-06-18 16:31  honoka_Gu  阅读(196)  评论(0)    收藏  举报