前端项目将网页生成图片或PDF文件以及解决PDF页面跨页问题

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

export function useHtml2Canvas() {
  /**
   * 捕获元素并转换为Canvas
   * @param {HTMLElement|string} target - 目标元素或选择器
   *  @param {number} scale - 图片清晰度
   * @param {object} options - html2canvas选项
   * @returns {Promise<HTMLCanvasElement>}
   */
  const captureToCanvas = async (target, scale?: number, options = {}) => {
    const targetEl = typeof target === 'string' ? document.querySelector(target) : target;

    if (!targetEl) throw new Error('未找到目标元素');

    return await html2canvas(targetEl, {
      scale: scale ? scale : 4,
      useCORS: true,
      ...options
    });
  };

  /**
   * 捕获元素并下载为图片
   * @param {HTMLElement|string} target - 目标元素或选择器
   * @param {string} filename - 文件名
   * @param {string} scale - 提高清晰度 (默认是4)
   * @param {object} options - html2canvas选项
   */
  const captureToImage = async (target, filename = 'screenshot', scale = 4, options = {}) => {
    const canvas = await captureToCanvas(target, scale, options);
    const link = document.createElement('a');
    link.download = `${filename}.png`;
    link.href = canvas.toDataURL('image/png');
    link.click();
  };

  /**
   * 捕获元素并下载为PDF(支持A3/A4等格式)
   * @param {HTMLElement|string} target - 目标元素或选择器
   * @param {string} filename - 文件名
   * @param {string} format - 纸张格式 (A3/A4等)
   * @param {string} scale - 提高清晰度 (默认是4)
   * @param {string} orientation - 方向 ('portrait' 纵向, 'landscape' 横向)
   */
  const captureToPDF = async (
    target: HTMLElement | string,
    filename = 'document',
    format = 'A4',
    scale?: number,
    orientation = 'portrait'
  ) => {
    const canvas = await captureToCanvas(target, scale ? scale : 4);

    // 创建PDF实例
    const pdf = new jsPDF(orientation as any, 'mm', format);

    // 计算图片尺寸以适应纸张
    // pdf的宽高
    const pdfWidth = format === 'A3' ? 297 : 210;
    const pdfHeight = format === 'A3' ? 420 : 297;

    // 画布宽高
    const canvasWidth = canvas.width;
    const canvasheight = (pdfHeight * canvas.width) / pdfWidth;

    // 生成图片的高度
    const imgHeight = (canvas.height * pdfWidth) / canvas.width;

    // 得到pdf页数向上取整
    const totalNumber = Math.ceil(imgHeight / pdfHeight);

    for (let i = 0; i < totalNumber; i++) {
      // 创建临时canvas,用于储存切分的初始canvas
      const tempCanvas = document.createElement('canvas');
      tempCanvas.width = canvasWidth;
      tempCanvas.height = canvasheight;

      // 将最初canvas分成多份,计算每份的高度
      const canvasHeightPerPage = i < totalNumber - 1 ? canvasheight : canvas.height - canvasheight * i;

      const ctx = tempCanvas.getContext('2d');
      if (!ctx) continue;

      // 填充背景颜色防止出现黑边
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, canvasWidth, canvasheight);
      // 在原始canvas中截取正确位置绘制在新画布中
      ctx.drawImage(
        canvas,
        0,
        i * canvasheight,
        canvas.width,
        canvasHeightPerPage,
        0,
        0,
        tempCanvas.width,
        canvasHeightPerPage
      );

      if (i > 0) pdf.addPage();

      // 添加到PDF
      const imgData = tempCanvas.toDataURL('image/jpeg');
      pdf.addImage(imgData, 'JPEG', 0, 0, pdfWidth, pdfHeight);
    }

    // 保存PDF
    pdf.save(`${filename}.pdf`);

    // 获取 PDF 的Blob二进制对象
    // const pdfArrayBlob = pdf.output('blob');
    // return pdfArrayBlob

    // 获取 PDF 的原始二进制数据
    // const pdfArraybuffer = pdf.output('arraybuffer');
    // return pdfArraybuffer
  };

  return {
    captureToCanvas,
    captureToImage,
    captureToPDF
  };
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值