Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money

Html2canvas is used to convert HTML pages into images, and then JSPDF is used to generate the image base64 into PDF files.

1. Installation and introduction

// Convert the page HTML to an image
npm install html2canvas --save  
// Create a PDF
npm install jspdf --save
Copy the code

Import and register the defined implementation method in the project main file main.js

import htmlToPdf from '@/utils/htmlToPdf';
// Using the vue.use () method calls the install method in the utility method
Vue.use(htmlToPdf);
Copy the code

Portal: Principle and use of vue.use () in Vue

2. Encapsulate and export PDF files

The configuration,

let pdf = new jsPDF('p'.'pt', [pdfX, pdfY]); The first parameter: L: horizontal p: vertical The second parameter: measurement unit ("pt"."mm"."cm"."m"."in" or "px"); The third parameter can be in the following format. The default value is a4. To customize the format, simply pass the size as an array of numbers, as in: [592.28.841.89];
		   a0 - a10
		   b0 - b10
		   c0 - c10
  		   dl
		   letter
		   government-letter
		   legal
		   junior-legal
		   ledger
		   tabloid
		   credit-card
Copy the code

Pdf.addpage () Adds a new page to the PDF document, default a4. The parameters are as follows:

AddImage () adds the image to the PDF. The parameters are as follows:

Delete a PDF page

let targetPage = pdf.internal.getNumberOfPages(); // Get the total page
pdf.deletePage(targetPage); // Delete the target page
Copy the code

Save PDF document

pdf.save(PDF `. ` test);
Copy the code

Encapsulate and export PDF files (utils/ htmltopdf.js)

// The export page is in PDF format
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default{
  install (Vue, options) {
    Vue.prototype.getPdf = function () {
      // When downloading the PDF, if it is not at the top of the page, it will cause the PDF style to be incorrect, so go back to the top of the page first
      let top = document.getElementById('pdfDom');
      if(top ! =null) {
        top.scrollIntoView();
        top = null;
      }
      let title = this.exportPDFtitle;
      html2Canvas(document.querySelector('#pdfDom'), {
        allowTaint: true
      }).then(function (canvas) {
        // Get the width and height of the canvas
        let contentWidth = canvas.width;
        let contentHeight = canvas.height;
	      // a PDF page displays the canvas height generated by the HTML page;
        let pageHeight = contentWidth / 841.89 * 592.28;
	      // Height of HTML page not generated PDF
        let leftHeight = contentHeight;
	      // Page offset
        let position = 0;
	      // Width and height of the canvas image in PDF generated by THE HTML page (for example: horizontal A4 paper [841.89,592.28], longitudinal size needs to be changed)
        let imgWidth = 841.89;
        let imgHeight = 841.89 / contentWidth * contentHeight;
        let pageData = canvas.toDataURL('image/jpeg'.1.0);
        let PDF = new JsPDF('l'.'pt'.'a4');
        // Two heights need to be distinguished: one is the actual height of the HTML page, and the page height of the generated PDF
        // When the content does not exceed the size of a PDF page, no pagination is required
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG'.0.0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG'.0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight;
            position -= 592.28;
            // Avoid adding blank pages
            if (leftHeight > 0) {
              PDF.addPage();
            }
          }
        }
        PDF.save(title + '.pdf')})}}}Copy the code

Application in related components

<template>
  <div class="wrap" >
    <div id="pdfDom" style="padding: 10px;">
      <el-table
        :data="tableData"
        border>
        <el-table-column prop="date" label="Date" width="250"></el-table-column>
        <el-table-column prop="name" label="Name" width="250"></el-table-column>
        <el-table-column prop="address" label="Address"></el-table-column>
      </el-table>
    </div>
    <button type="button" style="margin-top: 20px;" @click="btnClick">Export PDF</button>
  </div>

</template>
 
<script>
export default {
  data() { 
    return {
      exportPDFtitle: "Page export PDF file name".tableData: [{date: '2016-05-06'.name: 'Wang Xiaohu'.address: 'Torch Avenue, Jiulongpo District, Chongqing'
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: 'Torch Avenue, Jiulongpo District, Chongqing'}, {date: '2016-05-03'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-02'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-04'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-01'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-08'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-01'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-08'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: 'General Avenue, Jiangning District, Nanjing'
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: 'General Avenue, Jiangning District, Nanjing'}, {date: '2016-05-04'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-01'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-08'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai}, {date: '2016-05-01'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-08'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
        }, {
          date: '2016-05-08'.name: 'Wang Xiaohu'.address: Culture Avenue, Hongshan District, Wuhan city
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: Culture Avenue, Hongshan District, Wuhan city
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: Culture Avenue, Hongshan District, Wuhan city
        }, {
          date: '2016-05-06'.name: 'Wang Xiaohu'.address: 'General Avenue, Jiangning District, Nanjing'
        }, {
          date: '2016-05-07'.name: 'Wang Xiaohu'.address: Culture Avenue, Hongshan District, Wuhan city}}},],methods: {
    btnClick(){
      this.$nextTick(() = > {this.getPdf(); })},}},</script>  
Copy the code

The effect

Part to be optimized

  1. When paging, the page content is truncated (welcome to leave a message to discuss exchange);
  2. Different content, another page to start; Calculate the height beyond the content of the last page (set spacing = page height – the height beyond the part).