Last active
December 23, 2021 01:19
-
-
Save benshimmin/50ab957d3c7b12cf88f9c9113400db3c to your computer and use it in GitHub Desktop.
How to render a web page into a multi-page PDF with html2canvas and jsPDF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Assumptions: | |
# 1. $("#pdf-download") is something you can click on (not really required). | |
# 2. $(".result-page") is something in your existing page that you want to turn into a PDF. | |
# 3. You want to add a class of `pdf-rendered` to it and then specify some CSS which applies when that class is added. | |
# 4. Your CSS for `.pdf-rendered` specifies a useful width for a PDF (795px is pretty good) and anything else you like | |
# (this is for portrait ("p") PDFs; obviously you'll need to make a few modifications for landscape PDFs!). | |
# How it works: | |
# 1. Take the requested element in your existing page, clone it, add a "pdf-rendered" class to it, and append to | |
# the body. | |
# 2. Get the cloned element's height and use this to calculate how many `pages`. | |
# 3. For each page, turn the cloned element into a canvas using html2canvas, store the result in the `images` | |
# array, and then shift the content of the cloned element up by `pageCount` * `pageHeight`. | |
# 4. Repeat until you've run out of pages. | |
# 5. When done, call jsPDF and add a new page for each image in `images`, and add the image to the new page. | |
# 6. Save the PDF. | |
# Problems: | |
# 1. Yeah, it doesn't split the pages up very nicely. You'll have to live with that. | |
# 2. html2canvas doesn't understand all CSS, though it was fine for my examples. | |
# 3. I'm not convinced your pages won't end up out of order like this, though it didn't happen for me. | |
# 4. Why not just use the built-in functionality in your browser and OS to print a PDF? I don't know, maybe | |
# this is more flexible. | |
# 5. The PDFs generated are obviously pretty huge! | |
$("#pdf-download").on "click", -> | |
$toRender = $(".result-page").parent().clone().addClass "pdf-rendered" | |
# you can hide bits of the clone that you don't want to include in your PDF here using either | |
# CSS (.pdf-rendered .whatever { display : none }) or JavaScript ($toRender.remove(whatever)) | |
$("body").append $toRender | |
images = [] | |
pageHeight = 1110 | |
h = $toRender.height() | |
pages = Math.ceil(h / pageHeight) | |
pageCount = 0 | |
$toRender.css | |
overflow : "hidden" | |
height : pageHeight + 10 | |
render = -> | |
$toRender.find(".result-page").css | |
position : "relative" | |
top : -(pageHeight + 10) * pageCount | |
html2canvas $toRender, { | |
onrendered : (canvas) -> | |
imgData = canvas.toDataURL("image/png") | |
images.push imgData | |
if ++pageCount < pages | |
render() | |
else | |
done() | |
} | |
render() | |
done = -> | |
doc = new jsPDF("p", "mm") | |
_.each images, (image, i) -> | |
if i > 0 | |
doc.addPage() | |
doc.addImage(image, "PNG", 0, 0) | |
doc.save("output.pdf") | |
$toRender.remove() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment