html转PDF

项目场景:

提示:这里简述项目相关背景:

在项目中会有一些需要页面转成PDF的情况,这里需要配合一些插件可以完成

使用html2canvas将使用canvas将页面转为base64图片流,并插入jspdf插件中,保存并下载pdf。


安装依赖

提示:这里描述项目中遇到的问题:

javascript 复制代码
npm i html2canvas
npm i jspdf

解决方案1:

提示:这里填写该问题的具体解决方案:

1:创建htmlToPdf.ts文件

javascript 复制代码
// 页面导出为pdf格式
import html2Canvas from 'html2canvas';
import jsPDF from 'jspdf';

const htmlToPdf = {
  getPdf(title) {
    html2Canvas(document.querySelector('#pdfStyle'), {
      allowTaint: false,
      taintTest: false,
      logging: false,
      useCORS: true,
      dpi: window.devicePixelRatio * 4, //将分辨率提高到特定的DPI 提高四倍
      scale: 2, //按比例增加分辨率
    }).then((canvas) => {
      const pdf = new jsPDF('p', 'mm', 'a4'); //A4纸,纵向
      const ctx = canvas.getContext('2d')
      const a4w = 190
      const a4h = 272 //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
      //按A4显示比例换算一页图像的像素高度
      const imgHeight = Math.floor((a4h * canvas.width) / a4w) 
      let  renderedHeight = 0;
      while (renderedHeight < canvas.height) {
        const page = document.createElement('canvas');
        page.width = canvas.width;
        //可能内容不足一页
        page.height = Math.min(imgHeight, canvas.height - renderedHeight); 
        //用getImageData剪裁指定区域,并画到前面创建的canvas对象中
        page.getContext('2d')
          .putImageData(
            ctx.getImageData(
              0,
              renderedHeight,
              canvas.width,
              Math.min(imgHeight, canvas.height - renderedHeight),
            ),
            0,
            0,
          );
        pdf.addImage(
          page.toDataURL('image/jpeg', 1.0),
          'JPEG',
          10,
          10,
          a4w,
          Math.min(a4h, (a4w * page.height) / page.width),
        ); //添加图像到页面,保留10mm边距
        renderedHeight += imgHeight;
        if (renderedHeight < canvas.height) {
          pdf.addPage(); //如果后面还有内容,添加一个空页
        }
        // delete page;
      }
      //保存文件
      pdf.save(title + '.pdf');
      // loading = false;
      // console.log(loading);
    });
  },
};

export default htmlToPdf;

2:在页面中使用

javascript 复制代码
...
<!-- 按钮 -->
<el-button size="mini" type="primary" @click="pdfFunc" :loading="loading">
  转成pdf
</el-button>
...
<div id="pdfDom">
	<!-- 此处是希望转成pdf的部分的内容,用一个大div盒子包起来 -->
</div>
<script setup>
// 导入htmlToPdf.js
import htmlToPdf from '@/utils/htmlToPdf';
const pdfFunc = () => {
	 loading.value = true;
	 // 调用htmlToPdf工具函数
     htmlToPdf.getPdf('文档名称');
     // 定时器模拟按钮loading动画的时间
      setTimeout(() => {
        loading.value = false;
        ElMessage.success('打印成功!');
      }, 1000);
}
</script>

解决方案2:

1:创建htmlToPdf.ts文件

javascript 复制代码
// utils/htmlToPdf.js:导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

export default {
  install(Vue, options) {
    // id-导出pdf的div容器;title-导出文件标题
    Vue.prototype.htmlToPdf = (id, title) => {
      const element = document.getElementById(`${id}`)
      const opts = {
        scale: 12, // 缩放比例,提高生成图片清晰度
        useCORS: true, // 允许加载跨域的图片
        allowTaint: false, // 允许图片跨域,和 useCORS 二者不可共同使用
        tainttest: true, // 检测每张图片已经加载完成
        logging: true // 日志开关,发布的时候记得改成 false
      }

      html2Canvas(element, opts)
        .then((canvas) => {
          console.log(canvas)
          const contentWidth = canvas.width
          const contentHeight = canvas.height
          // 一页pdf显示html页面生成的canvas高度;
          const pageHeight = (contentWidth / 592.28) * 841.89
          // 未生成pdf的html页面高度
          let leftHeight = contentHeight
          // 页面偏移
          let position = 0
          // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
          const imgWidth = 595.28
          const imgHeight = (592.28 / contentWidth) * contentHeight
          const pageData = canvas.toDataURL('image/jpeg', 1.0)
          console.log(pageData)
          // a4纸纵向,一般默认使用;new JsPDF('landscape'); 横向页面
          const PDF = new JsPDF('', 'pt', 'a4')

          // 当内容未超过pdf一页显示的范围,无需分页
          if (leftHeight < pageHeight) {
            // addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
            PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
          } else {
            // 超过一页时,分页打印(每页高度841.89)
            while (leftHeight > 0) {
              PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
              leftHeight -= pageHeight
              position -= 841.89
              if (leftHeight > 0) {
                PDF.addPage()
              }
            }
          }
          PDF.save(title + '.pdf')
        })
        .catch((error) => {
          console.log('打印失败', error)
        })
    }
  }
}

2:在页面中使用

html 复制代码
<template>
  <div>
      <div
       id="pdfDom"
      >
        测试数据
      </div>
      <el-button 
        type="primary" round 
        style="background: #4849FF" 
        @click="btnClick">导出PDF</el-button>
    </div>
 </template>
 <script>
 import JsPDF from 'jspdf'
 import html2Canvas from 'html2canvas'
 mounted() {
    // 导出pdf
    btnClick() {
     this.$nextTick(() => {
         this.htmlToPdf('pdfDom', '个人报告')
     })
    },
  },
 </script>
相关推荐
恋猫de小郭24 分钟前
Android 官方给 Compose 搞了个不需要 UI 环境的 Composable
android·前端·flutter
珊瑚里的鱼1 小时前
C++的强制类型转换
android·开发语言·c++
问心无愧05132 小时前
ctf show web入门102
android·java·前端·笔记
暮云星影3 小时前
个人总结 docker搭建PDF操作工具
docker·容器·pdf
Kapaseker3 小时前
Kotlin 相等的奥义
android·kotlin
Lyyaoo.3 小时前
【MySQL】锁机制
android·数据库·mysql
DS随心转插件3 小时前
DeepSeek 代码手机端导出与 AI 辅助方案实测
android·人工智能·chatgpt·智能手机·deepseek·ai导出鸭
JohnnyDeng943 小时前
【Android】Flow vs LiveData:选型指南与迁移实践
android·kotlin·livedata·flow
plainGeekDev3 小时前
线程安全集合 → 协程安全替代
android·java·kotlin
zhangphil3 小时前
Kotlin管道Channel构造函数参数capacity值RENDEZVOUS与UNLIMITED
android·kotlin