-
-
Save poissoj/d79a520ca2a3377c15e902ec68790aff to your computer and use it in GitHub Desktop.
const PAGE_HEIGHT = 700; | |
const PAGE_WIDTH = 500; | |
const content = []; | |
function getPngDimensions (base64) { | |
const header = atob(base64.slice(22, 70)).slice(16, 24); | |
const uint8 = Uint8Array.from(header, c => c.charCodeAt(0)); | |
const dataView = new DataView(uint8.buffer); | |
return { | |
width: dataView.getInt32(0), | |
height: dataView.getInt32(4) | |
}; | |
} | |
const splitImage = (img, content, callback) => () => { | |
const canvas = document.createElement('canvas'); | |
const ctx = canvas.getContext('2d'); | |
const printHeight = img.height * PAGE_WIDTH / img.width; | |
canvas.width = PAGE_WIDTH; | |
for (let pages = 0; printHeight > pages * PAGE_HEIGHT; pages++) { | |
/* Don't use full height for the last image */ | |
canvas.height = Math.min(PAGE_HEIGHT, printHeight - pages * PAGE_HEIGHT); | |
ctx.drawImage(img, 0, -pages * PAGE_HEIGHT, canvas.width, printHeight); | |
content.push({ image: canvas.toDataURL(), margin: [0, 5], width: PAGE_WIDTH }); | |
} | |
callback(); | |
}; | |
function next () { | |
/* add other content here, can call addImage() again for example */ | |
pdfMake.createPdf({ content }).download(); | |
} | |
function addImage () { | |
/* Load big image */ | |
const image = 'data:image/png;base64,iVBORw0Kgo…'; | |
const { width, height } = getPngDimensions(image); | |
const printHeight = height * PAGE_WIDTH / width; | |
if (printHeight > PAGE_HEIGHT) { | |
const img = new Image(); | |
img.onload = splitImage(img, content, next); | |
img.src = image; | |
return; | |
} | |
content.push({ image, margin: [0, 5], width: PAGE_WIDTH }); | |
next(); | |
} | |
addImage(); |
Any angularjs version of this?
AngularJS should just work with this... it just runs JS and that's all this is.
Thanks for the code and insight @Balkoth. The split image definitely splits the image well and puts the different parts on different pages, but I noticed the image quality noticeably degraded. When using images small enough where splitImage
was not needed, quality seemed great. My project doesn't support ES6 so I had to convert this code to ES5, and I also decided to promisify things a bit, namely addImage
but those were all the changes I made.
Managed to work around the quality degradation issue by using html2canvas
to snapshot many smaller nodes as opposed to the whole page at once. Then instead of having to split one big image, a bunch of the smaller images can be concatenated and naturally overflow to the next page. This gives the consumer better control of how a site can be split up into multiple pdf pages. I posted a forked gist for reference (note its ES5).
New to Javascript and web deveIopment. I didn't understand what this function does exactly? Could please explain ?
Especially
const header = atob(base64.slice(22, 70)).slice(16, 24);
.Thanks in advance