搜索
简帛阁>技术文章>vue使用html2canvas和jspdf将html转成pdf

vue使用html2canvas和jspdf将html转成pdf

A4尺寸

A4纸的尺寸是210mm×297mm。

分辨率是72像素/英寸时,A4纸的尺寸的图像的像素是595×842(推荐用这个大小比例)。

分辨率是150像素/英寸时,A4纸的尺寸的图像的像素是1240×1754。

分辨率是300像素/英寸时,A4纸的尺寸的图像的像素是2479×3508。

选择不同的分辨率图像像素大小也会随之变化

安装插件html2canvas和jspdf

npm install html2canvas--save
npm install jspdf --save

html2canvas可以通过获取HTML的某个元素,然后生成Canvas,能让用户保存为图片。

jsPDF 是一个基于 HTML5 的客户端解决方案,用于生成各种用途的 PDF 文档。

在项目中引入

在utils 中 新建htmltopdf.js

htmlToPdf.js

// 导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default{
  install (Vue, options) {
    Vue.prototype.getPdf = function () {
      var pdfTitle = this.pdfTitle  //pdf的名称
      var pdfDom = document.querySelector('#pdfDom')
      html2Canvas(pdfDom, {
        allowTaint: true
      }).then(function (canvas) {
        console.log(canvas)
        const marginBottom = 34    // 项目页面显示微处理 以下用到的地方 可以忽略
        let canvasWidth = canvas.width 	//页面生成canvas宽度
        let canvasHeight = canvas.height + marginBottom //页面生成canvas高度
        let pageHeight = canvasWidth / 592.28 * 841.89 + marginBottom   //分页 每页的高度
        let allPageHeight = canvasHeight  // 所有页面的高度
        let position = 0 //偏移量
        let imgWidth = 595.28 //生成canvas 图片的宽度
        let imgHeight = 592.28 / canvasWidth * canvasHeight //生成canvas 图片的高度
        let pageData = canvas.toDataURL('image/jpeg', 3.0)
        // console.log(canvasWidth)
        // console.log(canvasHeight)
        // console.log(pageHeight)
        // console.log(allPageHeight)
        // console.log(position)
        // console.log(imgWidth)
        // console.log(imgHeight)
        // console.log(pageData)
        let PDF = new JsPDF('', 'pt', 'a4')
        if (allPageHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          // 循环生成分页
          while (allPageHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            allPageHeight = allPageHeight - pageHeight - marginBottom
            position = position - 841.89 - marginBottom
            if (allPageHeight > 0) {
              PDF.addPage() //添加新的一页
            }
          }
        }
        PDF.save(pdfTitle + '.pdf')  //保存pdf
      })
    }
  }
}

在main.ts 中 全局引入

main.ts

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import 'babel-polyfill'
import Vue from 'vue'
import App from './App.vue'
import router from './router/index.ts'
import store from './store/index.js'
import * as ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import htmlToPdf from '@/utils/htmlToPdf.js'
// 使用Vue.use()方法就会调用工具方法中的install方法
Vue.use(htmlToPdf)
// import 'swiper/dist/css/swiper.css'
// import * as VueAwesomeSwiper from 'vue-awesome-swiper'
// Vue.use(VueAwesomeSwiper)
Vue.config.productionTip = false
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

vue 页面

<template>
  <div class="transcript-container clearfix transcript-detail" @mouseenter.stop="pdfFlag = false">
    <div class="creat-pdf clearfix" @click.stop="pdfFlag = true;getPdf('#pdfDom')">下载pdf</div>
    <div id="pdfDom" class="clearfix" style="width: 210mm;margin: auto;"> </div>
  </div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { Getter, Action } from 'vuex-class'
@Component
export default class cousrseActivity extends Vue {
  @Getter commonData
  @Action transcriptDetail
  $refs: {
    onePage: HTMLElement,
    twoPage: HTMLElement
  }
  pdfTitle: string = ''
}
</script>
//对打印 做的 兼容
<style media="print" type="text/css">
  @page {
    size: auto;
    margin: 0mm;
  }
  /* 在chrome下可以使用background属性 */
  body {
    -webkit-print-color-adjust: exact;
  }
  @media print {
    .transcript-container.transcript-detail .transcript-wrap {
      margin-bottom: 0;
    }
  }
</style>

遇到的问题

多行省略号

多行省略号 在html2canvas 时 由于不能解析 display: -webkit-box; 会导致生成的图片 错误

.ellipsis{
  overflow : hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;      /* 可以显示的行数,超出部分用...表示*/
  -webkit-box-orient: vertical;
 }

目前 我这边正常显示时 使用多行省略号 在打印时 将 display: -webkit-box;改成display:blcok 就能正常显示了

图片模糊 生成的pdf 不清楚

解决办法: 将canvas的属性width和height属性放大为2倍,也就是,先将canvas高分辨率输出,再来压缩导出打印

// 导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default{
  install (Vue, options) {
    Vue.prototype.getPdf = function () {
      var pdfTitle = this.pdfTitle
      var pdfDom = document.querySelector('#pdfDom')
      var c = document.createElement('canvas')
      html2Canvas(pdfDom, {
        useCORS: true,
        scale: 2,
        canvas: c,
        logging: true,
        width: pdfDom.width,
        height: pdfDom.height
      // allowTaint: true
      }).then(function (canvas) {
        console.log(canvas)
        const marginBottom = 34
        let canvasWidth = canvas.width
        let canvasHeight = canvas.height + marginBottom * 2
        console.log(canvasWidth)
        console.log(canvasHeight)
        let pageHeight = canvasWidth / 592.28 * 841.89 + marginBottom * 2
        let allPageHeight = canvasHeight
        let position = 0
        let imgWidth = 595.28
        let imgHeight = 592.28 / canvasWidth * canvasHeight
        let pageData = canvas.toDataURL('image/jpeg', 3.0)
        // console.log(canvasWidth)
        // console.log(canvasHeight)
        // console.log(pageHeight)
        // console.log(allPageHeight)
        // console.log(position)
        // console.log(imgWidth)
        // console.log(imgHeight)
        // console.log(pageData)
        let PDF = new JsPDF('', 'pt', 'a4')
        if (allPageHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (allPageHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            allPageHeight = allPageHeight - pageHeight - marginBottom
            position = position - 841.89 - marginBottom
            if (allPageHeight > 0) {
              PDF.addPage()
            }
          }
        }
        PDF.save(pdfTitle + '.pdf')
      })
    }
  }
}

处理过的图片 能清晰一点 但是生成的pdf 也大了一倍

图片跨域 Tained canvases may not be exported

在test 服务器上 一点问题都没有 可以正常下载 一大包到线上 就开始报跨域的错误

百度了一下 基本都是一样的 复制来 复制去 给的办法 还是没发处理跨域的问题

看了一下html2canvas api 发现了 一个属性 proxy 代理完的图片 但是还是报跨域的问题 生成的pdf 还是没有图片

最后发现 页面里边的图片可以正产显示 只有外域的图片不能显示 本域的图片用base64显示的 外域的图片是不是也能用base64显示

base64 Data URL scheme 支持的类型:

  • data:,文本数据
  • data:text/plain,文本数据
  • data:text/html,HTML代码
  • data:text/html;base64,base64编码的HTML代码
  • data:text/css,CSS代码
  • data:text/css;base64,base64编码的CSS代码
  • data:text/JavaScript,Javascript代码
  • data:text/javascript;base64,base64编码的Javascript代码
  • data:image/gif;base64,base64编码的gif图片数据
  • data:image/png;base64,base64编码的png图片数据
  • data:image/jpeg;base64,base64编码的jpeg图片数据

将外域 的图片弄成base64 后 生成的pdf里边的图片 可以正常显示了 也不报跨域的问题了

总结

目录A4尺寸安装插件html2canvasjspdf在项目中引入遇到的问题多行省略号图片跨域Tainedcanvasesmaynotbeexportedbase64DataURLscheme支持的
结合html2canvasjsPDF实现html页面转pdfBy:授客QQ:103355122实践环境win10Vue296axios0180html2canvas100rc3jspdf153安装h
jspdfjs+html2canvasHTMl导出PDF功能:PDF分页插入页头页尾输出A4格式PDF支持单页、多页输出效果预览:查看演示PDFdemo地址:demo需要引入JS的文件:<sc
最近做项目中,🈶️遇到过实现模版打印功能,网上也找到很多资料可以实现,有的方式可以实现分页,但是打印的A4纸上下不能留边距,后来找到一个通过剪裁的方式可以实现左右上下留边距,并且能实现分页;方法如下
jsPdf是一个可以把html转成pdf的插件,有人多人在用。GitHub:https://githubcom/MrRio/jsPDF官方文档:http://rawgithackcom/MrRio/
<buttononclickHtmlToPdf()>转储pdf</button><buttononclickHtmlToImage()>转储image</b
1首先引入:importhtml2canvasfrom'//static/js/html2canvasminjs'23然后:4<dividcapturestylepadding:10px;ba
、需求来源:把可视化展示HTML页面打印成PDF文件报表二、html2canvas+jsPDF导出pdf原理:通过html2canvas遍历页面元素,并渲染生成canvas,然后canvas图片
html页面转pdf下载两个js文件可供使用,地址如下:https://githubcom/linwalker/renderhtmltopdf唯一的缺点是图片跨页不好解决,最终的pdf文件如下:解决下
一、前言我发现DOM转化为图片是一个非常常见的需求,而自己手动转是非常麻烦的,于是找到了html2canvas这个插件,既是用得比较多的也是维护得比较好的一个插件。注意:版本比较多,这里介绍最新版