Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blurry canvas if deviceScaleFactor > 1 #2755

Closed
iwan-uschka opened this issue Jun 16, 2018 · 8 comments · Fixed by #4319
Closed

blurry canvas if deviceScaleFactor > 1 #2755

iwan-uschka opened this issue Jun 16, 2018 · 8 comments · Fixed by #4319
Labels
chromium Issues with Puppeteer-Chromium

Comments

@iwan-uschka
Copy link

iwan-uschka commented Jun 16, 2018

Steps to reproduce

Tell us about your environment:

  • Puppeteer version: 1.5.0
  • Platform / OS version: Mac OS X 10.11.6
  • URLs (if applicable):
  • Node.js version: 9.4.0

What steps will reproduce the problem?

  1. Go to https://try-puppeteer.appspot.com/. Use the following code:
const browser = await puppeteer.launch();

const page = await browser.newPage();
await page.goto('https://www.google.de/maps/@52.5197103,13.4068538,16.11z');

await page.setViewport({
    width: 800,
    height: 600,
    deviceScaleFactor: 3
});

await page.waitFor(5000);

await page.screenshot({path: 'screenshot.png'});

await browser.close();
  1. Check screenshot and compare it against what you can see while browsing https://openlayersbook.github.io/ch06-styling-vector-layers/example-03.html on a retina display device in a real Chrome.

What is the expected result?
Sharp canvas.

What happens instead?
Blurry canvas.

@aslushnikov
Copy link
Contributor

@iwan-uschka I don't really see any blurriness; however, I didn't quite understand what do I compare it against in your step (2). The link https://openlayersbook.github.io/ch06-styling-vector-layers/example-03.html seems to be completely unrelated to the gmaps screenshot we do in (1).

However, I have one advice that might help: try emulating viewport before navigating page to the url.

const browser = await puppeteer.launch();

const page = await browser.newPage();
await page.setViewport({
    width: 800,
    height: 600,
    deviceScaleFactor: 3
});
await page.goto('https://www.google.de/maps/@52.5197103,13.4068538,16.11z');
await page.waitFor(5000);
await page.screenshot({path: 'screenshot.png'});
await browser.close();

This is important because canvas is usually set up with page dpi in mind, so page queries its DPI right away. Check out this hidpi canvas write-up for details.

Let me know if it helps.

@iwan-uschka
Copy link
Author

@aslushnikov Thanks a lot. It actually did help to set the viewport before loading the page, even if it's a web application and not a static page and the canvas gets loaded a few steps after opening the page.

Sorry for mixing up the google maps example with the openstreetmaps example.

pre set viewport:
pre-set-viewport

post set viewport:
post-set-viewport

I am using puppeteer to create app screenshots to use them within store presentations. Screenshots with different pixel ratios needs to be captured (@2x default, @3x for 5.5-Inch Retina).
Right now i open the app, do some JS navigation stuff and capture the view, set the viewport to other specific dimensions and pixel ratio, capture the view again, and again until every viewport has been captured. After that i navigate to the next view and do this routine again.

Doing it this way is not the right way regarding your advice because the page should be reloaded completely after switching viewports. It would take nearly twice the time capturing all views and change the viewport after it than capturing a view with all viewports and change the view after it.
Any ideas how to solve this?

@aslushnikov aslushnikov added the chromium Issues with Puppeteer-Chromium label Dec 6, 2018
@bbugh
Copy link

bbugh commented Mar 27, 2019

FYI if anyone else ends up here with a related issue, I was going to report that our iframes changed their rendering quality in a recent upgrade of puppeteer, but moving setViewport to before we set the page content fixed the problem.

@aslushnikov
Copy link
Contributor

FYI if anyone else ends up here with a related issue, I was going to report that our iframes changed their rendering quality in a recent upgrade of puppeteer, but moving setViewport to before we set the page content fixed the problem.

@bbugh can this be closed then?

@bbugh
Copy link

bbugh commented Apr 20, 2019

I think it is a bug. It was working fine for us on a previous puppeteer version (1.8.0) with setViewport after setContent, and then we upgraded to a later version (1.13.0) and we had to move it above the setContent. I would never have figured it out if not for your suggestion in this thread (thanks for that!). Since it was a breaking API change over a minor version, and it's not an intuitive or obvious workaround, I would call it a bug.

As far as a solution, I think one or all of:

  1. a warning if setViewport is called after setting the page content would prevent others from getting tripped up this.
  2. fix it so that it behaves as it did before the breaking change.
  3. add some documentation about the order of operations

@aslushnikov
Copy link
Contributor

a warning if setViewport is called after setting the page content would prevent others from getting tripped up this.

@bbugh Calling setViewport after page load is a totally legit usecase - this way you can simulate orientation changes, size changes and so on.

fix it so that it behaves as it did before the breaking change.

There's no behavior change; calling page.setViewport after page load is a race condition and always was. Check out the explanation in the end of this comment.

add some documentation about the order of operations

Fair enough: #4319

@bbugh
Copy link

bbugh commented Apr 20, 2019

That looks great to me! We actually got caught on setContent, not goto, but hopefully someone will either find this thread or the documentation if they get stuck. Maybe mention what possible scenarios could cause the issue? (canvas or iframes rendering blurry). Nice. 👍

@JoelEinbinder
Copy link
Collaborator

Just to be clear, if a canvas does not listen for DPI changes, that is a bug in the canvas. This can happen in the real world for example if a window is dragged between two monitors or the zoom is changed (on desktop). So while setting the viewport before the page is loaded might "fix" the problem, it is actually just avoiding a bug in the website.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chromium Issues with Puppeteer-Chromium
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants