Question and answer
headlines
column
The lecture hall
More and more

  • position
  • activity
  • The label
  • The badge

SegmentFault

  • Question and answer
  • headlines
  • column
  • The lecture hall
  • found
    • activity
    • Technology circle of hi
    • Looking for a job
    • list
    • The badge
    • notes
    • Development manual
    • advertising

  • Login immediatelyFree registration

all
The front end
The back-end
iOS
Android
security
Artificial intelligence (ai)
tool
The programmer
industry
SF, official

Javascript converts HTML to PDF, download it (HTML2Canvas and jsPDF)

Read 125, posted 1 day ago, source: bbs.thankbabe.com

I recently came across a requirement to generate a PDF of the current page and download it. Do a few days, myself sort out, write down, I think someone should need 🙂

Project source code address: github.com/linwalker/r…

html2canvas

Introduction to the

We can use HTML2Canvas directly on the browser side to take ‘screenshots’ of whole or partial pages. This is not an actual screenshot, but rather a CanvasImage rendered by traversing the DOM structure of the page, gathering all the element information and corresponding styles.

Html2canvas can only generate canvasimage as it can handle, so the rendered result is not 100% consistent with the original. But it doesn’t require a server, and the entire image is generated by the client browser, making it easy to use.

use

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

html2canvas(element, {
    onrendered: function(canvas) {
        // canvas is the final rendered <canvas> element
    }
});
Copy the code

The onRendered method makes it possible to send a generated canvas back, for example, to a page:

html2canvas(element, { onrendered: function(canvas) { document.body.appendChild(canvas); }});Copy the code

Make a small example code as follows, online show link demo1

<html> <head> <title>html2canvas example</title> <style type=&quot; text/css&quot; >... </style> </head> <body> <header> <nav> <ul> <li>one</li> ... </ul> </nav> </header> <section> <aside> <h3>it is a title</h3> <a href=&quot; &quot; >Stone Giant</a> ... </aside> <article> ! [](./Stone.png) <h2>Stone Giant</h2> <p>Coming ... </p> <p> With a ball of stone... </p> </article> </section> <footer>write by linwalker @2017</footer> <script type=&quot; text/javascript&quot; src=&quot; ./html2canvas.js&quot; ></script> <script type=&quot; text/javascript&quot; > html2canvas(document.body, { onrendered:function(canvas) { document.body.appendChild(canvas) } }) </script> </body> </html>Copy the code

This example renders the elements in the body of the page to a canvas and inserts them into the body

jsPDF

The jsPDF library can be used to generate PDFS on the browser side.

Text generation PDF

The usage method is as follows:

Var doc = new jsPDF(); // Add text 'Download PDF 'doc.text('Download PDF! ', 10, 10); doc.save('a4.pdf');Copy the code

Online demo2

Image generation PDF

The usage method is as follows:

// Three parameters, first direction, second unit, Var imageData = new jsPDF('landscape','pt',[205, 115]); base64,iVBORw0KGgo... "; doc.addImage(imageData, 'PNG', 0, 0, 205, 115); doc.save('a4.pdf');Copy the code

Online demo demo3

Text and images generate PDF

// Three parameters, first direction, second dimension, Var imageData = new jsPDF('landscape','pt',[205, 155]); base64,iVBORw0KGgo... "; // Set the font size doc.setfontSize (20); Doc. Text ('Stone', 10,20); AddImage (imageData, 'PNG', 0, 40, 205, 115); doc.save('a4.pdf')Copy the code

Online demo demo4

To generate PDF, you need to add the converted elements to the jsPDF instance. There is also the ability to add HTML, but some elements cannot be generated in PDF, so you can use HTML2Canvas +jsPDF to convert the page to PDF. Html2canvas will iterate through the page elements and render to generate canvas, then add canvas image format to jsPDF instance to generate PDF.

html2canvas + jsPDF

A single page

Modify the demo1 example:

<script type=&quot; text/javascript&quot; src=&quot; ./js/jsPdf.debug.js&quot; ></script> <script type=&quot; text/javascript&quot; > var downPdf = document.getElementById(&quot; renderPdf&quot;) ; Downpdf. onclick = function() {html2canvas(document.body, {oncanvas) {rendered:function(canvas) {// Var pageData = Canvas.todataURL ('image/ JPEG ', 1.0); Var PDF = new jsPDF(", 'pt', 'a4'); //addImage controls the size of the image. AddImage (pageData, 'JPEG', 0, 0, 595.28, 592.28/ cancanvas. Width * cancanvas. Height); pdf.save('stone.pdf'); } }) } </script>Copy the code

Online demo5

What if the page content is scaled to A4 and is taller than a4 paper? What happens to the resulting PDF? Will there be pagination?

Give it a try and test your ideas: Demo6

JsPDF provides a very useful API, addPage(), we can add a PDF page through pdf.addPage(), and then through pdf.addimage (…). , assign the image to the PDF page to display.

So how do we determine where to page?

This question is easy to answer, we can set a pageHeight, content above this height into the next page PDF.

Add the first page image to the PDF with addImage, add the PDF page number with addPage(), and then add the next page image to the PDF with addImage.

HMMM, good! Bart, don’t you see the problem?

The premise of this method is that — we can first divide the canvas picture generated by the whole page into corresponding small pictures according to pageHeight, and then add addImage page by page.

What? Think about where our canvas came from. Without pulling it up, look directly at the following:

html2canvas(document.body, {
    onrendered:function(canvas) {
     //it is here we handle the canvas
    }
})
Copy the code

The body here is the element object that generates the Canvas. Each element generates a canvas; So we need a page-by-page canvas, which means…

Do you think it’s possible? If you want to retrieve a DOM element from a different position on the page, then use htNL2Canvas (Element,option) to process it. If you want to find a DOM element from a different position on the page, then you can use htNL2Canvas (Element,option) to process it.

Tired words 🙂 can look at the following method

More pages

The idea I provided is that we only generate one canvas, yes one, and the conversion element is the parent element that you want to convert to the PDF content, which in this demo is the body; Everything else is the same, if there is more than one page, addPage, then addImage, only the same canvas is added here.

Of course, this will only appear multiple pages of duplicate PDF, that exactly how to achieve the correct pagination display. In fact, it mainly uses two points of jsPDF:

- Content larger than jsPDF instance format size is not displayed (var PDF = new jsPDF('', 'pt', 'a4'); AddImage has two parameters to control the position of the image in the PDFCopy the code

Although the images on each PDF page are the same, we create the illusion of pagination by repositioning the images. Take the second page as an example, set the offset in the vertical direction to -841.89, namely the height of a piece of A4 paper. Since the pictures beyond the height range of A4 paper are not displayed, the second page displays the contents in the range of [841.89,1682.78] in the vertical direction of the picture, so as to achieve the effect of paging, and so on.

Let’s look at the code:

html2canvas(document.body, { onrendered:function(canvas) { var contentWidth = canvas.width; var contentHeight = canvas.height; // a PDF page displays the canvas height generated by the HTML page; Var pageHeight = contentWidth / 592.28 * 841.89; // Don't generate PDF HTML page height var leftHeight = contentHeight; Var position = 0; Var imgWidth = 595.28; // The size of the a4 paper [595.28,841.89], the width of the canvas generated by the HTML page in PDF. Var imgHeight = 592.28/contentWidth * contentHeight; Var pageData = canvas.todataurl ('image/jpeg', 1.0); var pdf = new jsPDF('', 'pt', 'a4'); // There are two heights to distinguish, one is the actual height of the HTML page, and the page height of the generated PDF (841.89). 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; The position - = 841.89; // Avoid adding a blank page if(leftHeight > 0) {pdf.addPage(); } } } pdf.save('content.pdf'); }})Copy the code

Online demo7

Leave a margin on both sides

Change imgWidth and add addImage to the x direction parameter to set the margin you want as shown below

Var imgWidth = 555.28; Var imgHeight = 555.28/contentWidth * contentHeight; . pdf.addImage(pageData, 'JPEG', 20, 0, imgWidth, imgHeight ); . pdf.addImage(pageData, 'JPEG', 20, position, imgWidth, imgHeight);Copy the code

Online demo demo8


Old iron people pay attention to “Big Talk WEB Development” wechat public number, two-dimensional code ↓ mutual encouragement and learning exchange!

Read the original
Join the discussion ↩

  • Sina weibo
  • WeChat
  • Twitter
  • Facebook

• • •

More interesting articles

Browser artifact — Vimium

Vimium — A browser artifact

Start your Scala journey with IntelliJ IDEA and Maven

Start your Scala journey with IntelliJ IDEA and Maven

Front end series – unique mobile terminal fixed bottom bar fixed, absolute compatible with IOS and Android solutions

Trust me, the ultimate solution I share and you see on other blogs… View full text >

IphoneX adapter – client H5 page

Because the iphoneX has a full screen and a fringe, so… View full text >

More interesting articles

Browser artifact — Vimium

Vimium — A browser artifact

Start your Scala journey with IntelliJ IDEA and Maven

Start your Scala journey with IntelliJ IDEA and Maven

Front end series – unique mobile terminal fixed bottom bar fixed, absolute compatible with IOS and Android solutions

Trust me, the ultimate solution I share and you see on other blogs… View full text >

IphoneX adapter – client H5 page

Because the iphoneX has a full screen and a fringe, so… View full text >




  • Share it on Weibo
  • Share it on wechat
  • Share to the Twitter
  • Share to Facebook

Taking notes


xxxxxxxxxx

[舍弃]