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>
相关推荐
赏金术士3 小时前
Kotlin 从入门到进阶 之作用域函数 & 优雅写法(五)
android·开发语言·kotlin
小林敲代码77883 小时前
基于 PDFBox 的 PDF 水印管理:使用 OCG 层实现精准添加与一键去除
pdf
Ehtan_Zheng5 小时前
Android Compose 动画实践:内容切换与页面转场
android
Crystal3285 小时前
【终极指南】前端方面解决 uni-app APP 端 SSE 流式请求被缓冲拦截、无法实时渲染的问题
android·前端·ai编程
tanis_20775 小时前
学术论文 PDF 的版面自动还原:MinerU 对多栏排版、浮动图表与脚注区域的识别实战
人工智能·pdf·ocr
陆业聪6 小时前
技术选型决策树:什么团队、什么项目该选什么框架 | 跨平台框架深度对决(4)
android·架构设计
tanis_20776 小时前
从 PDF 中精准提取表格、图片与公式:MinerU 结构化元素抽取的 3 种方案
pdf
JohnnyDeng947 小时前
Kotlin 协程原理与 Android 中的最佳实践
android·kotlin·协程
Eric.Lee20217 小时前
python实现多个pdf合并
开发语言·python·pdf·pdf合并
Aleyn7 小时前
用 KSP 给 Navigation 3 加一层「跨模块路由」:nav3-helper 设计与使用
android·android jetpack·composer