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>
相关推荐
莞凰6 小时前
昇腾CANN的“灵脉根基“:Runtime仓库探秘
android·人工智能·transformer
NiceCloud喜云7 小时前
Claude Files API 深入:从上传、复用到配额管理的工程化指南
android·java·数据库·人工智能·python·json·飞书
ujainu7 小时前
CANN pto-isa:虚拟指令集如何连接编译与执行
android·ascend
赏金术士8 小时前
第六章:UI组件与Material3主题
android·ui·kotlin·compose
shuaiqinke9 小时前
分享噪音测试分贝仪 精准测噪 数据直观超实用
pdf
TechMerger9 小时前
Android 17 重磅重构!服役 20 年的 MessageQueue 迎来无锁改造,卡顿大幅优化!
android·性能优化
yuhuofei202112 小时前
【Python入门】Python中字符串相关拓展
android·java·python
dalancon12 小时前
Android Input Spy Window
android
NiceCloud喜云13 小时前
Claude API PDF 文档问答实战:从原生解析到分页引用的完整方案
java·服务器·前端·网络·数据库·人工智能·pdf
dalancon13 小时前
InputDispatcher派发事件,查找目标窗口
android