Reputation: 3200
I am trying to generate pdf with multiple iframes using puppeteer. One issue I encounter is that if I embed something like google maps, google maps will do lazily load(it only loads when the element is in view point of the browser. One solution is to scroll through different iframes on the page and set a wait time for each iframe to load.
here is what I have so far (able to test in https://try-puppeteer.appspot.com/) puppeteer: version 1.9.0, I also tried in 1.12.0, could not make the scroll to work nor the timeout.
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({
width: 1280,
height: 750
});
await page.emulateMedia('screen');
const html = '<iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe><div><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe></div><div><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe></div><div><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe></div>'
await page.setContent(html, { waitUntil: 'networkidle0' });
const frames = await page.mainFrame().childFrames(); // get all the iframes on that page.
await page.evaluate((frames) => {
// this part does not work
for (let i=0, i<frames.length; i++){
setTimeout(() => {
document.querySelectorAll('iframe')[i].scrollIntoView();
}, 2000)
}
}, frames)
const pdf = await page.pdf({
scale: 1,
printBackground: true,
margin: { bottom: 0 },
path: 'screenshot.pdf'
});
await browser.close();
Any help is appreciated!
Upvotes: 1
Views: 1540
Reputation: 13772
This code has some issues:
frames
is a non-serializable object from Node.js context so it cannot be transferred in the browser context as is.setTimeout()
callbacks will be called at once after 2 sec so each frame will not have enough time to be loaded.setTimeout()
callbacks are not awaited: page.evaluate()
returns before these 2 sec pass and pdf creation happens before iframe loading.You can try this approach:
// page loaded
await page.evaluate(async () => {
for (const iframe of Array.from(document.querySelectorAll('iframe'))) {
iframe.scrollIntoView();
await new Promise((resolve) => { setTimeout(resolve, 2000); });
}
});
// pdf creation
Upvotes: 1