asny / three-d

2D/3D renderer - makes it simple to draw stuff across platforms (including web)
MIT License
1.24k stars 105 forks source link

Wrong viewport on web+mobile #338

Open asny opened 1 year ago

asny commented 1 year ago

Open this example in a browser on mobile and see that the green line is not going from top left corner to bottom right corner of the browser viewport.

The problem is that Window::innerWidth() used here includes the browser header and similar. Same for height. It's only a problem on mobile though. It seems like visualViewport might be correct, but that's not exposed by the web_sys crate.

huand commented 8 months ago

I guess this is also why object are not centered and aspect ratio is wrong? (see that the circle is not really a circle on the Shapes example on mobile)

Screenshot_2023-10-29-08-59-15-524_com android chrome

asny commented 7 months ago

Yeah, I think so. Any help with this is much appreciated, I basically just need a way to get the correct viewport (without the browser header) from the web API, the rest is simple.

huand commented 6 months ago

Hi again, sorry i dont come with a solution, just some observations i just did:

Also I'm a bit surprised by the canvas size.

log::warn!(
    "browser inner width/height: {} --- {}",
    browser_window.inner_width().unwrap().as_f64().unwrap(),
    browser_window.inner_height().unwrap().as_f64().unwrap()
);
log::warn!(
    "canvas width/height: {} xxx {}",
    html_canvas.width(),
    html_canvas.height()
);

gives the log (in pc browser)

browser inner width/height: 1423 --- 971
canvas width/height: 2846 xxx 1942

is it normal that they are not in the same "unit"? it seems that the inner values are logical pixel but canvas physical (factor 2 between the 2) but the function HtmlCanvasElement::Width() should actually gives logical pixel if i understand it correctly. So this would mean that we have a canvas actually too big by pixel_ratio factor. Would that be possible?

Screenshot_2023-12-13-16-43-44-498_com android chrome Screenshot_2023-12-13-16-48-34-144_com android chrome

huand commented 6 months ago

So going to the original live demo on mobile, and halving my screen size by 2 with the split screen phone feature, actually the example works (ratio + accurate touching)

You can see in the upper half of the image the the correct view.

I dont know where to go from this ? any idea?

Screenshot_2023-12-13-17-36-08-757_com android chrome

huand commented 6 months ago

so i went on with this : browser inner size == canvas size. the change required then are for the viewport function + GUI mouse position and then it seems functional for me but i'm not sure that this is the correct fix?

huand commented 6 months ago

after Xmas I can open a PR for this so some more knowledgeable people could review this, as usability/fidelity on mobile web could be a nice to have for some projects.

asny commented 6 months ago

Thank you so much for looking into this @huand 🙏

I've spend a lot of time on these kind of problems, especially when I handled the canvas myself. A year ago or something, I realized that winit started supporting web so I removed my own code and started using that. I since realized that winit web support is not very good 😕 so it is possible that this is a bug in winit.

However, I think it's something else. To make the canvas cover the entire document I set the CSS margins to zero in index.html. That might be the issue since that will make the canvas be underneath the header as well? And the width and height that we retrieve to set the viewport is without that header and then the canvas width height is different from the screen viewport and we get the problem?

About canvas physical size, if the dpr is 2, the canvas size needs to be twice as big as the canvas logical size in the document, otherwise we'll get a pixelated result. It is very confusing, took me a long time to understand that.

The split screen experiment might be better than without split screen but it is still wrong. The green line doesn't hit the corner exactly.

I'll be very happy to review a PR, though I'm not sure I'm more knowledgeable than you 😄 just so you know, I'm perfectly ok with a hack if that's what it takes, just as long as it doesn't add a lot of code.

huand commented 6 months ago

For info, I saw in winit changelog a lot of changes lately. Maybe there is some stuff related to this issue? It might be worth it to try to upgrade this dependency?