Skip to content

Instantly share code, notes, and snippets.

@stacklast
Created May 3, 2023 15:58
Show Gist options
  • Select an option

  • Save stacklast/dd5601f39baeb853be3b0816c2729d08 to your computer and use it in GitHub Desktop.

Select an option

Save stacklast/dd5601f39baeb853be3b0816c2729d08 to your computer and use it in GitHub Desktop.
Using html2canvas and jsPDF to download html as PDF.
/*
letterSettings: {
MARGIN_INCHES: 0.5,
WIDTH_INCHES: 8.5,
HEIGHT_INCHES: 11
}
*/
import constants from "../constants";
import { jsPDF } from "jspdf";
import * as html2canvas from "html2canvas";
export default async function downloadPdf(htmElement, fileName, isSigned = false) {
// To avoid the image will be cut by scroll, we need to scroll top before html2canvas.
window.pageYOffset = 0;
document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
const options = {
scale: 1,
allowTaint: true,
useCORS: true,
scrollY: 0,
backgroundColor: '#FFFFFF',
removeContainer: true,
imageTimeout: 15000,
windowWidth: '1280px',
onclone: function (clonedDoc) {
const signatures = clonedDoc.getElementsByClassName('signature');
if (signatures.length > 0) {
let tempSignature = signatures[0];
let newSignatureText = document.createElement('span');
newSignatureText.className = tempSignature.className + ' signature-clone';
newSignatureText.innerText = tempSignature.value ? tempSignature.value : tempSignature.placeholder;
tempSignature.parentNode.replaceChild(newSignatureText,tempSignature);
}
const textAreas = clonedDoc.querySelectorAll('textarea');
if (textAreas.length > 0) {
for (let index = 0; index < textAreas.length; index++) {
const textArea = textAreas[index];
const newTextAreaDiv = clonedDoc.createElement('div');
newTextAreaDiv.className = textArea.className + ' textarea-clone';
newTextAreaDiv.setAttribute('contenteditable', true);
newTextAreaDiv.innerText = textArea.value ? textArea.value : textArea.placeholder;
textArea.parentNode.replaceChild(newTextAreaDiv,textArea);
}
}
},
ignoreElements: function (element) {
if ('e-signature-container' == element.id && !isSigned) {
return true;
}
if ('button' == element.tagName.toLowerCase()) {
return true;
}
}
};
await html2canvas(htmElement, options).then(canvas => {
const image = { type: 'image/jpeg', quality: 1.0 };
const imgWidth = constants.letterSettings.WIDTH_INCHES;
const pageHeight = constants.letterSettings.HEIGHT_INCHES;
const fullHeightPixels = canvas.height;
const innerPageWidth = imgWidth - constants.letterSettings.MARGIN_INCHES * 2;
const pageHeightPixels = Math.floor(canvas.width * (pageHeight / imgWidth));
const numberOfPages = Math.ceil(fullHeightPixels / pageHeightPixels);
let innerPageHeight = pageHeight - constants.letterSettings.MARGIN_INCHES * 2;
let pageCanvas = document.createElement('canvas');
let pageContext = pageCanvas.getContext('2d');
pageCanvas.width = canvas.width;
pageCanvas.height = pageHeightPixels;
let pdf = new jsPDF('p', 'in', [imgWidth, pageHeight]);
pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen');
for (let page = 0; page < numberOfPages; page++) {
if (page === numberOfPages - 1 && fullHeightPixels % pageHeightPixels !== 0) {
pageCanvas.height = fullHeightPixels % pageHeightPixels;
innerPageHeight = (pageCanvas.height * innerPageWidth) / pageCanvas.width;
}
pageContext.fillStyle = 'white';
pageContext.fillRect(0, 0, pageCanvas.width, pageCanvas.height);
pageContext.drawImage(canvas, 0, page * pageHeightPixels, pageCanvas.width, pageCanvas.height, 0, 0, pageCanvas.width, pageCanvas.height);
if (page > 0) {
pdf.addPage();
}
let imgData = pageCanvas.toDataURL('image/' + image.type, image.quality);
pdf.addImage(imgData, image.type, constants.letterSettings.MARGIN_INCHES, constants.letterSettings.MARGIN_INCHES, innerPageWidth, innerPageHeight);
}
if (iOS) {
const link = pdf.output("bloburl");
const a = document.createElement("a");
a.href = link;
a.target = '_blank';
a.download = fileName +'.pdf';
a.click();
} else {
pdf.save(fileName +'.pdf');
}
}).catch(error => {
console.error("Error " + error);
});
}
/*
HOW TO USE
const htmElement = document.getElementById('contract-pdf-container');
const fileName = 'filename';
await downloadPdf(htmElement, fileName, this.controller.isSigned);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment