The experience summary of exporting pdf in the foreground (html2canvas.js and the browser's own printing function - print.js) and some methods of exporting pdf in the background

Keywords: Javascript html5 html

Two ways to export pdf from the foreground

html2canvas.js & pdf.js

brief introduction

We can directly use html2canvas on the browser side to 'screenshot' the whole or part of the page. However, this is not a real screenshot, but by traversing the page DOM structure, collecting all element information and corresponding styles, and rendering the canvas image.

Because html2canvas can only generate canvas image s that it can handle, the rendered results are not 100% consistent with the original. However, it does not require the participation of the server. The whole picture is generated by the client browser, which is very convenient to use.

use

Download the html2canvas.js and jspdf plug-ins first:

yarn add html2canvas
npm install --save html2canvas

yarn add jspdf
npm install jspdf –save

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

The API used is also very concise. The following code can render an element as a canvas:

html2canvas(element, {
    onrendered: function(canvas) {
       document.body.appendChild(canvas);
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Of course, this is a very simple js method to convert html into pdf.

Problems and Solutions

If we want to output multi page pdf, what should we do if we need higher definition and the content is not truncated?

  1. Output multi page pdf
// //Export page in PDF format
import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
       // Place the scroll bar at the top before exporting, otherwise incomplete data will appear
        window.pageYOffset = 0
       document.documentElement.scrollTop = 0
        document.body.scrollTop = 0
        var element = document.getElementById('pdfCentent')
        element.style.background = '#FFFFFF'
        html2canvas(element, {
         logging: false,
         dpi: window.devicePixelRatio * 4, // Increase the resolution to a specific DPI by four times
         scale: 4, // Increase resolution proportionally
         element: element,
         backgroundColor: '#ffffff',
         allowTaint: true,
        useCORS: true
       }).then(function (canvas) {
         var pdf = new JSPDF('p', 'mm', 'a4') // A4 paper, longitudinal
         pdf.setFontSize(30) // font size
         // pdf.text(20, 30, pdf)
         var ctx = canvas.getContext('2d')
         var a4w = 170; var a4h = 257 // A4 size, 210mm x 297mm, 20mm margin shall be reserved on four sides, and the display area is 170x257
         var imgHeight = Math.floor(a4h * canvas.width / a4w) // Convert the pixel height of one page of image according to A4 display scale
         var renderedHeight = 0
        var options = { pagesplit: true }
     <span class="token keyword">while</span> <span class="token punctuation">(</span>renderedHeight <span class="token operator">&lt;</span> canvas<span class="token punctuation">.</span>height<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
       <span class="token keyword">var</span> page <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'canvas'</span><span class="token punctuation">)</span>
       page<span class="token punctuation">.</span>width <span class="token operator">=</span> canvas<span class="token punctuation">.</span>width
       page<span class="token punctuation">.</span>height <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>imgHeight<span class="token punctuation">,</span> canvas<span class="token punctuation">.</span>height <span class="token operator">-</span> renderedHeight<span class="token punctuation">)</span><span class="token comment">// The content may be less than one page</span>

       <span class="token comment">// Clip the specified area with getImageData and draw it into the canvas object created earlier</span>
       page<span class="token punctuation">.</span><span class="token function">getContext</span><span class="token punctuation">(</span><span class="token string">'2d'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">putImageData</span><span class="token punctuation">(</span>ctx<span class="token punctuation">.</span><span class="token function">getImageData</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> renderedHeight<span class="token punctuation">,</span> canvas<span class="token punctuation">.</span>width<span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>imgHeight<span class="token punctuation">,</span> canvas<span class="token punctuation">.</span>height <span class="token operator">-</span> renderedHeight<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
       pdf<span class="token punctuation">.</span><span class="token function">addImage</span><span class="token punctuation">(</span>page<span class="token punctuation">.</span><span class="token function">toDataURL</span><span class="token punctuation">(</span><span class="token string">'image/jpeg'</span><span class="token punctuation">,</span> <span class="token number">1.0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'JPEG'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> a4w<span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>a4h<span class="token punctuation">,</span> a4w <span class="token operator">*</span> page<span class="token punctuation">.</span>height <span class="token operator">/</span> page<span class="token punctuation">.</span>width<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// Add image to page with 10mm margin</span>

       renderedHeight <span class="token operator">+=</span> imgHeight
       <span class="token keyword">if</span> <span class="token punctuation">(</span>renderedHeight <span class="token operator">&lt;</span> canvas<span class="token punctuation">.</span>height<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> pdf<span class="token punctuation">.</span><span class="token function">addPage</span><span class="token punctuation">(</span>element<span class="token punctuation">,</span> options<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token comment">// If there is more content, add an empty page</span>
       <span class="token comment">// delete page;</span>
     <span class="token punctuation">}</span>
     pdf<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>htmlTitle <span class="token operator">+</span> currentTime<span class="token punctuation">)</span>
   <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2. Higher definition:

// //Export page in PDF format
import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
       // Higher definition
       var downPdf = document.getElementById('pdfCentent')
       html2canvas(downPdf, {
            logging: false,
           //  dpi: 172,
            dpi: window.devicePixelRatio * 4, // Increase the resolution to a specific DPI by four times
            scale: 4 // Increase resolution proportionally
                    }).then(function (canvas) {
                      console.log('canvas: ', canvas)
                         var contentWidth = canvas.width
                         var contentHeight = canvas.height
                     <span class="token comment">// One page pdf displays the height of the canvas generated by the html page</ span>
                     <span class="token keyword">var</span> pageHeight <span class="token operator">=</span> contentWidth <span class="token operator">/</span> <span class="token number">592.28</span> <span class="token operator">*</span> <span class="token number">841.89</span>
                     <span class="token comment">// html page height without pdf generated</span>
                    <span class="token keyword">var</span> leftHeight <span class="token operator">=</span> contentHeight
                     <span class="token comment">// pdf page offset</span>
                     <span class="token keyword">var</span> position <span class="token operator">=</span> <span class="token number">0</span>
                     <span class="token comment">// Width and height of canvas generated from html page in pdf (a4 paper size [595.28841.89])</span>
                     <span class="token keyword">var</span> imgWidth <span class="token operator">=</span> <span class="token number">595.28</span>
                     <span class="token keyword">var</span> imgHeight <span class="token operator">=</span> <span class="token number">592.28</span> <span class="token operator">/</span> contentWidth <span class="token operator">*</span> contentHeight

                    <span class="token keyword">var</span> pageData <span class="token operator">=</span> canvas<span class="token punctuation">.</span><span class="token function">toDataURL</span><span class="token punctuation">(</span><span class="token string">'image/jpeg'</span><span class="token punctuation">,</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
                     <span class="token keyword">var</span> pdf <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">JSPDF</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">,</span> <span class="token string">'pt'</span><span class="token punctuation">,</span> <span class="token string">'a4'</span><span class="token punctuation">)</span>

                     <span class="token comment">// There are two heights that need to be distinguished. One is the actual height of the html page and the height of the generated pdf page (841.89)</span>
                    <span class="token comment">// When the content does not exceed the range displayed on one page of pdf, pagination is not required</span>
                     <span class="token keyword">if</span> <span class="token punctuation">(</span>leftHeight <span class="token operator">&lt;</span> pageHeight<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                        pdf<span class="token punctuation">.</span><span class="token function">addImage</span><span class="token punctuation">(</span>pageData<span class="token punctuation">,</span> <span class="token string">'JPEG'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> imgWidth<span class="token punctuation">,</span> imgHeight<span class="token punctuation">)</span>
                     <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                         <span class="token keyword">while</span> <span class="token punctuation">(</span>leftHeight <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                             pdf<span class="token punctuation">.</span><span class="token function">addImage</span><span class="token punctuation">(</span>pageData<span class="token punctuation">,</span> <span class="token string">'JPEG'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> position<span class="token punctuation">,</span> imgWidth<span class="token punctuation">,</span> imgHeight<span class="token punctuation">)</span>
                             leftHeight <span class="token operator">-=</span> pageHeight
                             position <span class="token operator">-=</span> <span class="token number">841.89</span>
                             <span class="token comment">// Avoid adding blank pages</span>
                             <span class="token keyword">if</span> <span class="token punctuation">(</span>leftHeight <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                                 pdf<span class="token punctuation">.</span><span class="token function">addPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                             <span class="token punctuation">}</span>
                         <span class="token punctuation">}</span>
                     <span class="token punctuation">}</span>
                     pdf<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>htmlTitle <span class="token operator">+</span> currentTime<span class="token punctuation">)</span>
                     <span class="token comment">// The background is set to white (black by default)</span>
                     <span class="token comment">// background: '#fff'</span>
                <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

3. The content is not truncated, that is, put all the content on one page:

// //Export page in PDF format
import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
       // -------------Output pdf as one page to solve the problem of page content truncation. Errors will occur when printing pdf alone-------------
      var mainRight = document.getElementById('pdfCentent')
            html2canvas(mainRight, {
              allowTaint: true,
              scale: 2 // Improve picture quality, but increase file size
            }).then(function (canvas) {
  var contentWidth = canvas.width
  var contentHeight = canvas.height

var pageData = canvas.toDataURL('image/jpeg', 0.4)

var pdfWidth = (contentWidth + 10) / 2 0.75
Var pdfheight = (contentheight + 200) / 2 0.75 / / 500 is left blank at the bottom

var imgWidth = pdfWidth
var imgHeight = (contentHeight / 2 * 0.75) / / there is no need to leave a blank distance in the content image

var pdf = new JSPDF('', 'pt', [pdfWidth, pdfHeight])
pdf.addImage(pageData, 'jpeg', 0, 0, imgWidth, imgHeight)
// pdf.save('report_pdf_' + new Date().getTime() + '.pdf')
pdf.save(htmlTitle + currentTime)
})
}
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Question:
Using this plug-in can convert html into pdf output, but the principle is to convert html into canvas pictures first, and then convert the pictures into pdf. In this way, the clarity of the pictures is not high, and the contents are truncated. Although it can be judged whether to truncate the contents by modifying js files, there are many designed text contents, such as tables, text, pictures Charts, etc., are hard to judge.
Therefore, the following method is used to export pdf from the foreground, and print.js is used.

The browser's own printing function & print.js

brief introduction

The browser's own printing function can also output pdf. The graphic evidence is as follows:

use

Two import methods:
1. Introduce and install vue-print.js:

cnpm i vue-printjs --save-dev

 
  • 1

2. Download the print.js package:
https://github.com/zxc19890923/print/blob/master/print.js
usage method
1. Introducing plug-ins in main.js

import Print from './plugins/print/Print'
Vue.use(Print)

 
  • 1
  • 2

2. Used in Vue project:

<!--
 * @Autor: Sugar_W
 * @Date: 2020-11-24 19:01:10
 * @LastEditors: Sugar_W
 * @LastEditTime: 2020-11-24 19:55:32
 * @Description: Still waters run deep!
 * @FilePath: \CPSWeb\src\views\report\ReportTest.vue
-->
<template>
  <div>
    <template>
      <div ref="print" class="app-container" id="print">
        <p>
          qhfqihbfhubqshufbuqhwbufbqwuvfbugsdghjcbhjasbvfgyugqwetyggdfytgqwvgtgyufvbaswdguyhfb
        </p>
        <a-button type="primary" class="button" @click="printContext">
          query
        </a-button>
      </div>
    </template>

</div>
</template>

<script>

export default {
methods: {
//Print
printContext () {
this. p r i n t < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > < s p a n c l a s s = " t o k e n k e y w o r d " > t h i s < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > . < / s p a n > print</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span> print</span><spanclass="tokenpunctuation">(</span><spanclass="tokenkeyword">this</span><spanclass="tokenpunctuation">.</span>refs.print)
}
//Do not print method 1. Add no print style class
//Do not print method 2. this p r i n t ( t h i s . print(this. print(this.refs.print,{'no-print':'.do-not-print-div'})
}
}
</script>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

Problems and Solutions

There are few people using this plug-in, so I still encounter many problems in the project. Let's solve them one by one. Programmers solve problems, QAQ.
1. If the project requires multiple pages of pdf, it must be paged. First, determine the size of each page to adapt to your interface, because everyone has different needs and sizes. Here is the size I set:

// Report right block style
.reportBlock{
  border-radius: 2px;
  border:1px solid;
  border-color:#dcdddd;
  width:731px;
  height:1024px;
  clear: both;
  margin: 0 auto;
  position: relative;
  margin-top: 20px;
  margin-left: 0px;
  margin-bottom: 20px;
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2. When the size of each page is determined, paging needs to be implemented. Here, a css style is used:

page-break-after: always; // An important step in paging

 
  • 1

The whole code is:

// Report right block style
.reportBlock{
  border-radius: 2px;
  border:1px solid;
  border-color:#dcdddd;
  width:731px;
  height:1024px;
  clear: both;
  margin: 0 auto;
  position: relative;
  margin-top: 20px;
  margin-left: 0px;
  margin-bottom: 20px;
  page-break-after: always; // An important step in paging
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3. Since there is paging, you naturally need a scroll bar. You will not use the scroll bar provided by the browser, which will affect the use of the whole system. Moreover, if the interface content uses scroll bars, the appearance of scroll bars is not beautiful, especially for our front-end developers. We can use two div blocks:

.rightBlock{
  overflow: hidden;
  width: 840px;
  height: 750px;
  }

 
  • 1
  • 2
  • 3
  • 4
  • 5

The first div block is empty, and the setting width is small to block the scroll bar of the second div;

.printBlock{
  width: 860px;
  height: 100%;
  overflow-y: scroll;
  overflow-x: hidden;
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Put the content we need to display in the second div block, set scrollable, and then set the width to be greater than the width of the first Div.
In this way, both scroll bars and hidden are realized.
Note that this css attribute cannot be used here:

min-height:666px;max-height:666px;overflowY:scroll;

 
  • 1

This css style will cause paging failure!

4. When the print preview pops up, you will find that the header and footer appear, which needs to be removed. Use the following code:

// Remove header and footer
#print{
  @page {
      margin: 0; /* this affects the margin in the printer settings */
    }
    }

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

The print here is the corresponding div block that you want to output pdf.

5. In places that need to be blank, such as the first page, we first thought about whether to add a rectangular box, but it proved to be a failure. You need to use the css outer border attribute, similar to margin top. Instead of adding a div box.

6. If your project uses ecarts charts and cannot be printed and displayed directly in the browser, because print.js itself does not support the function of converting canvas into pictures, you need to convert ecarts into pictures and convert canvas charts into pictures in advance. Here you use your own code. Remember that the code here is in print.js of main.js just introduced:

var canvass = document.querySelectorAll('canvas');

 
  • 1

//Convert canvas echars chart to picture
    for (var k4 = 0; k4 < canvass.length; k4++) {
      var imageURL = canvass[k4].toDataURL("image/png");
      var img = document.createElement("img");
      img.src = imageURL;
      img.setAttribute('style', 'max-width: 100%;');
      img.className = 'isNeedRemove'
      // canvass[k4].style.display = 'none'
      // canvass[k4].parentNode.style.width = '100%'
      // canvass[k4].parentNode.style.textAlign = 'center'
      canvass[k4].parentNode.insertBefore(img,canvass[k4].nextElementSibling);
    }

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

The paging function is also written in print.js:

//Do paging
    //style="page-break-after: always"
    var pages = document.querySelectorAll('.result');
    for (var k5 = 0; k5 < pages.length; k5++) {
      pages[k5].setAttribute('style', 'page-break-after: always');
    }
    return this.dom.outerHTML;

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

writeIframe: function (content) {
    var w, doc, iframe = document.createElement('iframe'),
      f = document.body.appendChild(iframe);
    iframe.id = "myIframe";
    //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
    iframe.setAttribute('style', 'position:absolute;width:' + document.querySelector('.results').clientWidth + 'px;height:0;top:-10px;left:-10px;');
    w = f.contentWindow || f.contentDocument;
    doc = f.contentDocument || f.contentWindow.document;
    doc.open();
    doc.write(content);
    doc.close();
<span class="token keyword">var</span> removes <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.isNeedRemove'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k <span class="token operator">&lt;</span> removes<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> _this <span class="token operator">=</span> <span class="token keyword">this</span>
iframe<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
  _this<span class="token punctuation">.</span><span class="token function">toPrint</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>iframe<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

},

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Worried that you can't find the location, take a screenshot to mark the places you need to add, and then put the code underground for you to copy. After all, we are all CV oriented programming, QAQ.
But some partners say that it's too hard to find one by one. I just want to meet you directly. Here's what I want:

// Print class properties and method definitions
/* eslint-disable */
const Print = function (dom, options) {
  if (!(this instanceof Print)) return new Print(dom, options);

this.options = this.extend({
'noPrint': '.no-print'
}, options);

if ((typeof dom) === "string") {
this.dom = document.querySelector(dom);
} else {
this.isDOM(dom)
this.dom = this.isDOM(dom) ? dom : dom.$el;
}

this.init();
};
Print.prototype = {
init: function () {
var content = this.getStyle() + this.getHtml();
this.writeIframe(content);
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k];
}
return obj;
},

getStyle: function () {
var str = "",
styles = document.querySelectorAll('style,link');
for (var i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += "<style>" + (this.options.notPrint ? this.options.notPrint : '.no-print') + "{display:none;}</style>";
str += "<style>.results{width:100%!important;} .result .title{width:100%;}</style>";

<span class="token keyword">return</span> str<span class="token punctuation">;</span>

},

getHtml: function () {
var inputs = document.querySelectorAll('input');
var textareas = document.querySelectorAll('textarea');
var selects = document.querySelectorAll('select');
var canvass = document.querySelectorAll('canvas');
for (var k = 0; k < inputs.length; k++) {
if (inputs[k].type "checkbox" || inputs[k].type "radio") {
if (inputs[k].checked true) {
inputs[k].setAttribute('checked', "checked")
} else {
inputs[k].removeAttribute('checked')
}
} else if (inputs[k].type "text") {
inputs[k].setAttribute('value', inputs[k].value)
} else {
inputs[k].setAttribute('value', inputs[k].value)
}
}

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k2 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k2 <span class="token operator">&lt;</span> textareas<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k2<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>textareas<span class="token punctuation">[</span>k2<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">'textarea'</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    textareas<span class="token punctuation">[</span>k2<span class="token punctuation">]</span><span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> textareas<span class="token punctuation">[</span>k2<span class="token punctuation">]</span><span class="token punctuation">.</span>value
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k3 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k3 <span class="token operator">&lt;</span> selects<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k3<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>selects<span class="token punctuation">[</span>k3<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">'select-one'</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">var</span> child <span class="token operator">=</span> selects<span class="token punctuation">[</span>k3<span class="token punctuation">]</span><span class="token punctuation">.</span>children<span class="token punctuation">;</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token keyword">in</span> child<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>tagName <span class="token operator">==</span> <span class="token string">'OPTION'</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>selected <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
          child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'selected'</span><span class="token punctuation">,</span> <span class="token string">"selected"</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
          child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'selected'</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//Convert canvas echars chart to picture</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k4 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k4 <span class="token operator">&lt;</span> canvass<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k4<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  <span class="token keyword">var</span> imageURL <span class="token operator">=</span> canvass<span class="token punctuation">[</span>k4<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">toDataURL</span><span class="token punctuation">(</span><span class="token string">"image/png"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">var</span> img <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"img"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  img<span class="token punctuation">.</span>src <span class="token operator">=</span> imageURL<span class="token punctuation">;</span>
  img<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'style'</span><span class="token punctuation">,</span> <span class="token string">'max-width: 100%;'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  img<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'isNeedRemove'</span>
  <span class="token comment">// canvass[k4].style.display = 'none'</span>
  <span class="token comment">// canvass[k4].parentNode.style.width = '100%'</span>
  <span class="token comment">// canvass[k4].parentNode.style.textAlign = 'center'</span>
  canvass<span class="token punctuation">[</span>k4<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">insertBefore</span><span class="token punctuation">(</span>img<span class="token punctuation">,</span>canvass<span class="token punctuation">[</span>k4<span class="token punctuation">]</span><span class="token punctuation">.</span>nextElementSibling<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//Do paging</span>
<span class="token comment">//style="page-break-after: always"</span>
<span class="token keyword">var</span> pages <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.result'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k5 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k5 <span class="token operator">&lt;</span> pages<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k5<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  pages<span class="token punctuation">[</span>k5<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'style'</span><span class="token punctuation">,</span> <span class="token string">'page-break-after: always'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>dom<span class="token punctuation">.</span>outerHTML<span class="token punctuation">;</span>

},

writeIframe: function (content) {
var w, doc, iframe = document.createElement('iframe'),
f = document.body.appendChild(iframe);
iframe.id = "myIframe";
//iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
iframe.setAttribute('style', 'position:absolute;width:' + document.querySelector('.results').clientWidth + 'px;height:0;top:-10px;left:-10px;');
w = f.contentWindow || f.contentDocument;
doc = f.contentDocument || f.contentWindow.document;
doc.open();
doc.write(content);
doc.close();

<span class="token keyword">var</span> removes <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.isNeedRemove'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k <span class="token operator">&lt;</span> removes<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> _this <span class="token operator">=</span> <span class="token keyword">this</span>
iframe<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
  _this<span class="token punctuation">.</span><span class="token function">toPrint</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>iframe<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

},

toPrint: function (frameWindow) {
try {
setTimeout(function () {
frameWindow.focus();
try {
if (!frameWindow.document.execCommand('print', false, null)) {
frameWindow.print();
}
} catch (e) {
frameWindow.print();
}
frameWindow.close();
}, 10);
} catch (err) {
console.log('err', err);
}
},
isDOM: (typeof HTMLElement = 'object') ?
function (obj) {
return obj instanceof HTMLElement;
} :
function (obj) {
return obj && typeof obj = 'object' && obj.nodeType = 1 && typeof obj.nodeName = 'string';
}
};
const MyPlugin = { }
MyPlugin.install = function (Vue, options) {
//4. Add instance method
Vue.prototype.$print = Print
}
export default MyPlugin

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159

7. Sometimes, when previewing, a blank page will appear in the middle, which may be caused by the problem of your component. For example, the vue card I used and the encapsulated internal margin padding:24px will lead to this.
Two solutions:
1. If you want to change all your card s or a component you reference, changing the inline style will not affect others. You can use the deep inline deep of vue to change:

/deep/.ant-transfer-list-header{
  background: #01ada8;
}

 
  • 1
  • 2
  • 3

Like this, it's useless for me to change the card specifically. This small problem is not a big problem for all watchers, so I'll solve it myself.
2. Just change the card to div.

summary
The front desk output pdf is here. There may be some problems that haven't been written in it. They will be updated in the future. You are also welcome to ask questions and make common progress.

Background output pdf

Export with iText

Because I used the foreground export, I also looked at the background at that time. Because there are many complex charts in the project, the background can't realize it, so I gave up this way. Children should also pay attention when making choices.
Here are some blogs I read at that time, hoping to help you!
1,iText5 realizes the full version of PDF files generated by Java
2,iText5 official series of tutorials - iText in Action (I)
3,[iText5 generate PDF] generate PDF with pure Java code (custom table, text watermark, cell style)
Articles designed for streaming to foreground and background files:
1,Pdf function realization 1 - Java realizes dynamic pages and generates PDF files in the background
2,Automatically generate PDF documents from dynamic jsp pages (or static html) and upload them to the server
3,The front end accepts the back-end file stream and downloads it locally
4,The background returns the file stream, and the front end realizes the Preview pdf

Posted by kurdishvoice on Sun, 19 Sep 2021 02:50:44 -0700