it编程 > 编程语言 > Javascript

前端实现HTML网页转PDF并导出

15人参与 2025-02-14 Javascript

有个新需求,当点击【下载】按钮时,直接将当前 html页面下载为 pdf。通过 html2canvas + jspdf 可实现pdf单页下载,甚至是多页下载,记录分享一下~ 最后有源码,可自取

html2canvas

html2canvas官网在这:html2canvas - screenshots with javascript

html2canvas 是一个 html 渲染器。该脚本允许你直接在用户浏览器截取页面或部分网页的“屏幕截屏”,通过读取 dom 以及应用于元素的不同样式,将当前页面呈现为 canvas 图像

安装 html2canvas

npm install --save html2canvas

截取页面生成canvas,并将其插入页面中

html2canvas(document.body}).then(function(canvas) {
    document.body.appendchild(canvas);
});

注意:受限于浏览器的实现,html 的 canvas 元素也有高度限制 可参考 canvas 最大画布尺寸 - mdn

jspdf

jspdf文档可以看这:github - parallax/jspdf: client-side javascript pdf generation for everyone.

安装 jspdf

npm install jspdf --save

api也很简单,下面是个生成文本和图片的pdf样例

// jspdf 下载文本图片pdf
const downloadpdf = () => {
  // 三个参数,第一个方向,第二个单位,第三个尺寸 'a4' = [595.28,841.89]
  const doc = new jspdf('', 'pt', [500, 1000])

  // 字体大小
  doc.setfontsize(50)

  // 文本,左边距,上边距
  doc.text('hello world!', 10, 50)

  // base64,图片类型,左边距,上边距,宽度,高度
  doc.addimage(base64, 'png', 10, 60, 400, 200)

  doc.save('a4.pdf')
}

注意: jspdf 生成的 pdf 默认以 pt (point) 为单位,单页的最大高度通常限制在 14400 pt。超过这个高度可能导致生成的 pdf 无法正确渲染或浏览器崩溃⚠

html2canvas + jspdf 实现页面下载

单页下载(自适应纸)

pdf页面的宽高 采用 canvas的宽高

如果页面很长的话,单页下载就会生成一张长长的pdf。注意!超过限制就会显示空白页面, jspdf 生成的 pdf单页最大高度为 14400pt

canvas也有最大高度限制 32767像素,如果页面过长的话,通过 html2canvas 生成 canvas会失败

const downloadpdfautosingle = () => {
  html2canvas(document.body, {
    scale: window.devicepixelratio * 2, // 使用设备的像素比 * 2
  }).then(canvas => {
    // 返回图片dataurl,参数:图片格式和清晰度(0-1)
    const pagedata = canvas.todataurl('image/jpeg', 1.0)

    const pagewidth = canvas.width
    const pageheight =  canvas.height
    const orientation = canvas.height >= canvas.width ? 'portrait' : 'landscape'  // portrait 表示纵向,landscape表示横向
    const pdf = new jspdf(orientation, 'pt', [pagewidth, pageheight])
    
    // addimage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
    pdf.addimage(
      pagedata,
      'jpeg',
      0,
      0,
      pagewidth,
      pageheight
    )
    pdf.save('下载一页pdf(自适应纸).pdf')
  })
}

单页下载(a4纸)

已知:a4纸的宽度 和 canvas的宽度高度。可得 canvas在a4纸上占用的总高度(a4纸尺寸为宽 595.28pt,高 841.89pt)

如果页面很长的话,单页下载就会生成一张长长的pdf。注意!超过限制就会显示空白页面, jspdf 生成的 pdf单页最大高度为 14400pt

canvas也有最大高度限制 32767像素,如果页面过长的话,通过 html2canvas 生成 canvas会失败

const downloadpdfa4single = () => {
  html2canvas(document.body).then(canvas => {
    // 返回图片dataurl,参数:图片格式和清晰度(0-1)
    const pagedata = canvas.todataurl('image/jpeg', 1.0)

    // 方向纵向,尺寸ponits,纸张格式 a4 即 [595.28, 841.89]
    const a4width = 595.28
    const a4height = 841.89 // a4纸宽
    const pageheight = a4height >= a4width * canvas.height / canvas.width ? a4height :  a4width * canvas.height / canvas.width
    const pdf = new jspdf('portrait', 'pt', [a4width, pageheight])
    
    // addimage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
    pdf.addimage(
      pagedata,
      'jpeg',
      0,
      0,
      a4width,
      a4width * canvas.height / canvas.width,
    )
    pdf.save('下载一页pdf(a4纸).pdf')
  })
}

多页下载(自适应纸)

由于 jspdf 单页最大高度的限制 又或是 需求层面,我们需要实现自动分页下载

我们设置一页pdf页面宽度为canvas.width,高度为canvas.width * 1.3

分页思路:每个pdf页面都显示一张 canvas 图,只不过是计算偏移量,每个pdf页面显示的是 canvas 的不同位置

问题来了,如何创建一个新的pdf页面呢?可以使用 jspdf 的pdf.addpage()

const downloadpdfautomultiple = () => {
  const ele = document.body
  html2canvas(ele, {
    scale: window.devicepixelratio * 2, // 使用设备的像素比 * 2
  }).then(canvas => {
    let position = 0 //页面偏移
    const autowidth = canvas.width // 一页纸宽度
    const autoheight = canvas.width * 1.3 // 一页纸高度

    // 一页pdf可显示的canvas高度
    const pageheight = (canvas.width * autoheight) / autowidth
    // 未分配到pdf的canvas高度
    let unallottedheight = canvas.height

    // canvas对应的pdf宽高
    const imgwidth = canvas.width
    const imgheight = canvas.height

    const pagedata = canvas.todataurl('image/jpeg', 1.0)
    const pdf = new jspdf('', 'pt', [autowidth, autoheight])

    // 当canvas高度 未超过 一页pdf可显示的canvas高度,无需分页
    if (unallottedheight <= pageheight) {
      pdf.addimage(pagedata, 'jpeg', 0, 0, imgwidth, imgheight)
      pdf.save('下载多页pdf(自适应纸).pdf')
      return
    }

    while (unallottedheight > 0) {
      pdf.addimage(pagedata, 'jpeg', 0, position, imgwidth, imgheight)
      unallottedheight -= pageheight
      position -= autoheight
      if (unallottedheight > 0) {
        pdf.addpage()
      }
    }
    pdf.save('html2canvas+jspdf下载pdf.pdf')
  })
}

多页下载(a4纸)

由于 jspdf 单页最大高度的限制 又或是 需求层面,我们需要实现自动分页下载

我们设置一页pdf页面的宽高为a4纸尺寸,即宽 595.28pt,高 841.89pt

分页思路:每个pdf页面都显示一张 canvas 图,只不过是计算偏移量,每个pdf页面显示的是 canvas 的不同位置

问题来了,如何创建一个新的pdf页面呢?可以使用 jspdf 的pdf.addpage()

const downloadpdfa4multiple = () => {
  const ele = document.body
  html2canvas(ele, {
    scale: 2, // 使用设备的像素比
  }).then(canvas => {
    let position = 0 //页面偏移
    const a4width = 595.28 // a4纸宽度
    const a4height = 841.89 // a4纸宽

    // 一页pdf可显示的canvas高度
    const pageheight = (canvas.width * a4height) / a4width
    // 未分配到pdf的canvas高度
    let unallottedheight = canvas.height

    // canvas对应的pdf宽高
    const imgwidth = a4width
    const imgheight = (a4width * canvas.height) / canvas.width

    const pagedata = canvas.todataurl('image/jpeg', 1.0)
    const pdf = new jspdf('', 'pt', [a4width, a4height])

    // 当canvas高度 未超过 一页pdf可显示的canvas高度,无需分页
    if (unallottedheight <= pageheight) {
      pdf.addimage(pagedata, 'jpeg', 0, 0, imgwidth, imgheight)
      pdf.save('下载多页pdf(a4纸).pdf')
      return
    }

    while (unallottedheight > 0) {
      pdf.addimage(pagedata, 'jpeg', 0, position, imgwidth, imgheight)
      unallottedheight -= pageheight
      position -= a4height
      if (unallottedheight > 0) {
        pdf.addpage()
      }
    }
    pdf.save('下载多页pdf(a4纸).pdf')
  })
}

源码

github - burc-li/vue-pdf: html 转 pdf下载(html2canvas 和 jspdf实现)

到此这篇关于前端实现html网页转pdf并导出的文章就介绍到这了,更多相关html网页转pdf内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

uni-app封装axios进行请求响应拦截和token设置的操作指南

02-14

JavaScript模拟GET请求并携带指定Cookie的代码示例

02-14

前端优雅实现防抖和节流的几种方法示例

02-14

JavaScript超过Number最大值的解决方案

02-14

Sortable.js功能强大的JavaScript 拖拽库示例详解

02-14

javascript中延迟加载的7种方法实现

02-14

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论