I have a js file with puppeteer to generate a large report in pdf. Everything works pretty fine except for the canvas. In react file this is the basic logic for chartjs:
useEffect((): void => {
if (refChart && refChart.current) {
const newChartInstance = new Chart(refChart.current, chartConfig);
newChartInstance.options.animation = {
onComplete: (): void => {
if (refImage && refImage.current) {
refImage.current.src = newChartInstance.toBase64Image();
}
},
};
}
}, [refChart]);
return (
<>
<canvas ref={refChart} style={{ display: (printing) ? 'none' : 'block' }} width="100%" />
<img
alt="printing chart"
ref={refImage}
className={classes.chartImage}
style={{
display: (printing) ? 'block' : 'none',
}}
/>
</>
);
If I open url or if I print it (CTRL + P) the images are shown in place of canvas but in puppeteer my pdf has the (broken) canvas with wrong size (even with printing locked as true).
This is what I expect and I can see in browser and printing:
And this is what I got from puppeteer:
Can anybody please help me with this? Thanks in advance.
I've found the solution adding page.setViewport()
in puppeteer. This is my final code:
const puppeteer = require('puppeteer');
module.exports = async (callback, url) => {
const browser = await puppeteer.launch({
headless: true,
executablePath: (process.platform === 'win32') ? null : '/usr/bin/chromium-browser',
args: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage'],
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log('lauch: ', err);
});
const page = await browser.newPage()
.catch((err) => {
// eslint-disable-next-line no-console
console.log('page: ', err);
});
await page.setViewport({
width: 1280,
height: 1024,
deviceScaleFactor: 1,
});
await page.goto(`${url}/pdf`, {
waitUntil: ['load', 'domcontentloaded', 'networkidle0', 'networkidle2'],
timeout: 0,
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log('goto: ', err);
});
await page.evaluate(async () => {
let scrollPosition = 0;
let documentHeight = document.body.scrollHeight;
while (documentHeight > scrollPosition) {
window.scrollBy(0, documentHeight);
// eslint-disable-next-line no-await-in-loop
await new Promise((resolve) => {
setTimeout(resolve, 100);
});
scrollPosition = documentHeight;
documentHeight = document.body.scrollHeight;
}
});
// await page.evaluate(async () => {
// const matches = document.querySelectorAll('img');
// matches.forEach((canv) => {
// // eslint-disable-next-line no-param-reassign
// canv.style.maxWidth = '80%';
// });
// });
const buffer = await page.pdf({
// path: 'hn.pdf',
format: 'a4',
margin: {
top: '1cm',
bottom: '1.5cm',
},
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log('page.pdf: ', err);
});
await browser.close()
.catch((err) => {
// eslint-disable-next-line no-console
console.log('close: ', err);
});
const base64 = buffer.toString('base64');
return callback(null, base64);
};