-
Notifications
You must be signed in to change notification settings - Fork 333
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
Canvas scaling on the example pages breaks mouse click events #371
Labels
Comments
bors bot
pushed a commit
to bevyengine/bevy
that referenced
this issue
May 20, 2022
Currently Bevy's web canvases are "fixed size". They are manually set to specific dimensions. This might be fine for some games and website layouts, but for sites with flexible layouts, or games that want to "fill" the browser window, Bevy doesn't provide the tools needed to make this easy out of the box. There are third party plugins like [bevy-web-resizer](https://github.com/frewsxcv/bevy-web-resizer/) that listen for window resizes, take the new dimensions, and resize the winit window accordingly. However this only covers a subset of cases and this is common enough functionality that it should be baked into Bevy. A significant motivating use case here is the [Bevy WASM Examples page](https://bevyengine.org/examples/). This scales the canvas to fit smaller windows (such as mobile). But this approach both breaks winit's mouse events and removes pixel-perfect rendering (which means we might be rendering too many or too few pixels). bevyengine/bevy-website#371 In an ideal world, winit would support this behavior out of the box. But unfortunately that seems blocked for now: rust-windowing/winit#2074. And it builds on the ResizeObserver api, which isn't supported in all browsers yet (and is only supported in very new versions of the popular browsers). While we wait for a complete winit solution, I've added a `fit_canvas_to_parent` option to WindowDescriptor / Window, which when enabled will listen for window resizes and resize the Bevy canvas/window to fit its parent element. This enables users to scale bevy canvases using arbitrary CSS, by "inheriting" their parents' size. Note that the wrapper element _is_ required because winit overrides the canvas sizing with absolute values on each resize. There is one limitation worth calling out here: while the majority of canvas resizes will be triggered by window resizes, modifying element layout at runtime (css animations, javascript-driven element changes, dev-tool-injected changes, etc) will not be detected here. I'm not aware of a good / efficient event-driven way to do this outside of the ResizeObserver api. In practice, window-resize-driven canvas resizing should cover the majority of use cases. Users that want to actively poll for element resizes can just do that (or we can build another feature and let people choose based on their specific needs). I also took the chance to make a couple of minor tweaks: * Made the `canvas` window setting available on all platforms. Users shouldn't need to deal with cargo feature selection to support web scenarios. We can just ignore the value on non-web platforms. I added documentation that explains this. * Removed the redundant "initial create windows" handler. With the addition of the code in this pr, the code duplication was untenable. This enables a number of patterns: ## Easy "fullscreen window" mode for the default canvas The "parent element" defaults to the `<body>` element. ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, ..default() }) ``` And CSS: ```css html, body { margin: 0; height: 100%; } ``` ## Fit custom canvas to "wrapper" parent element ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, canvas: Some("#bevy".to_string()), ..default() }) ``` And the HTML: ```html <div style="width: 50%; height: 100%"> <canvas id="bevy"></canvas> </div> ```
james7132
pushed a commit
to james7132/bevy
that referenced
this issue
Jun 7, 2022
…gine#4726) Currently Bevy's web canvases are "fixed size". They are manually set to specific dimensions. This might be fine for some games and website layouts, but for sites with flexible layouts, or games that want to "fill" the browser window, Bevy doesn't provide the tools needed to make this easy out of the box. There are third party plugins like [bevy-web-resizer](https://github.com/frewsxcv/bevy-web-resizer/) that listen for window resizes, take the new dimensions, and resize the winit window accordingly. However this only covers a subset of cases and this is common enough functionality that it should be baked into Bevy. A significant motivating use case here is the [Bevy WASM Examples page](https://bevyengine.org/examples/). This scales the canvas to fit smaller windows (such as mobile). But this approach both breaks winit's mouse events and removes pixel-perfect rendering (which means we might be rendering too many or too few pixels). bevyengine/bevy-website#371 In an ideal world, winit would support this behavior out of the box. But unfortunately that seems blocked for now: rust-windowing/winit#2074. And it builds on the ResizeObserver api, which isn't supported in all browsers yet (and is only supported in very new versions of the popular browsers). While we wait for a complete winit solution, I've added a `fit_canvas_to_parent` option to WindowDescriptor / Window, which when enabled will listen for window resizes and resize the Bevy canvas/window to fit its parent element. This enables users to scale bevy canvases using arbitrary CSS, by "inheriting" their parents' size. Note that the wrapper element _is_ required because winit overrides the canvas sizing with absolute values on each resize. There is one limitation worth calling out here: while the majority of canvas resizes will be triggered by window resizes, modifying element layout at runtime (css animations, javascript-driven element changes, dev-tool-injected changes, etc) will not be detected here. I'm not aware of a good / efficient event-driven way to do this outside of the ResizeObserver api. In practice, window-resize-driven canvas resizing should cover the majority of use cases. Users that want to actively poll for element resizes can just do that (or we can build another feature and let people choose based on their specific needs). I also took the chance to make a couple of minor tweaks: * Made the `canvas` window setting available on all platforms. Users shouldn't need to deal with cargo feature selection to support web scenarios. We can just ignore the value on non-web platforms. I added documentation that explains this. * Removed the redundant "initial create windows" handler. With the addition of the code in this pr, the code duplication was untenable. This enables a number of patterns: ## Easy "fullscreen window" mode for the default canvas The "parent element" defaults to the `<body>` element. ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, ..default() }) ``` And CSS: ```css html, body { margin: 0; height: 100%; } ``` ## Fit custom canvas to "wrapper" parent element ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, canvas: Some("#bevy".to_string()), ..default() }) ``` And the HTML: ```html <div style="width: 50%; height: 100%"> <canvas id="bevy"></canvas> </div> ```
Closing as fixed, although we may need to redeploy. |
to use bevyengine/bevy#4726 on the website we will need to update some things on this side |
ItsDoot
pushed a commit
to ItsDoot/bevy
that referenced
this issue
Feb 1, 2023
…gine#4726) Currently Bevy's web canvases are "fixed size". They are manually set to specific dimensions. This might be fine for some games and website layouts, but for sites with flexible layouts, or games that want to "fill" the browser window, Bevy doesn't provide the tools needed to make this easy out of the box. There are third party plugins like [bevy-web-resizer](https://github.com/frewsxcv/bevy-web-resizer/) that listen for window resizes, take the new dimensions, and resize the winit window accordingly. However this only covers a subset of cases and this is common enough functionality that it should be baked into Bevy. A significant motivating use case here is the [Bevy WASM Examples page](https://bevyengine.org/examples/). This scales the canvas to fit smaller windows (such as mobile). But this approach both breaks winit's mouse events and removes pixel-perfect rendering (which means we might be rendering too many or too few pixels). bevyengine/bevy-website#371 In an ideal world, winit would support this behavior out of the box. But unfortunately that seems blocked for now: rust-windowing/winit#2074. And it builds on the ResizeObserver api, which isn't supported in all browsers yet (and is only supported in very new versions of the popular browsers). While we wait for a complete winit solution, I've added a `fit_canvas_to_parent` option to WindowDescriptor / Window, which when enabled will listen for window resizes and resize the Bevy canvas/window to fit its parent element. This enables users to scale bevy canvases using arbitrary CSS, by "inheriting" their parents' size. Note that the wrapper element _is_ required because winit overrides the canvas sizing with absolute values on each resize. There is one limitation worth calling out here: while the majority of canvas resizes will be triggered by window resizes, modifying element layout at runtime (css animations, javascript-driven element changes, dev-tool-injected changes, etc) will not be detected here. I'm not aware of a good / efficient event-driven way to do this outside of the ResizeObserver api. In practice, window-resize-driven canvas resizing should cover the majority of use cases. Users that want to actively poll for element resizes can just do that (or we can build another feature and let people choose based on their specific needs). I also took the chance to make a couple of minor tweaks: * Made the `canvas` window setting available on all platforms. Users shouldn't need to deal with cargo feature selection to support web scenarios. We can just ignore the value on non-web platforms. I added documentation that explains this. * Removed the redundant "initial create windows" handler. With the addition of the code in this pr, the code duplication was untenable. This enables a number of patterns: ## Easy "fullscreen window" mode for the default canvas The "parent element" defaults to the `<body>` element. ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, ..default() }) ``` And CSS: ```css html, body { margin: 0; height: 100%; } ``` ## Fit custom canvas to "wrapper" parent element ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, canvas: Some("#bevy".to_string()), ..default() }) ``` And the HTML: ```html <div style="width: 50%; height: 100%"> <canvas id="bevy"></canvas> </div> ```
Subserial
pushed a commit
to Subserial/bevy_winit_hook
that referenced
this issue
Jan 24, 2024
Currently Bevy's web canvases are "fixed size". They are manually set to specific dimensions. This might be fine for some games and website layouts, but for sites with flexible layouts, or games that want to "fill" the browser window, Bevy doesn't provide the tools needed to make this easy out of the box. There are third party plugins like [bevy-web-resizer](https://github.com/frewsxcv/bevy-web-resizer/) that listen for window resizes, take the new dimensions, and resize the winit window accordingly. However this only covers a subset of cases and this is common enough functionality that it should be baked into Bevy. A significant motivating use case here is the [Bevy WASM Examples page](https://bevyengine.org/examples/). This scales the canvas to fit smaller windows (such as mobile). But this approach both breaks winit's mouse events and removes pixel-perfect rendering (which means we might be rendering too many or too few pixels). bevyengine/bevy-website#371 In an ideal world, winit would support this behavior out of the box. But unfortunately that seems blocked for now: rust-windowing/winit#2074. And it builds on the ResizeObserver api, which isn't supported in all browsers yet (and is only supported in very new versions of the popular browsers). While we wait for a complete winit solution, I've added a `fit_canvas_to_parent` option to WindowDescriptor / Window, which when enabled will listen for window resizes and resize the Bevy canvas/window to fit its parent element. This enables users to scale bevy canvases using arbitrary CSS, by "inheriting" their parents' size. Note that the wrapper element _is_ required because winit overrides the canvas sizing with absolute values on each resize. There is one limitation worth calling out here: while the majority of canvas resizes will be triggered by window resizes, modifying element layout at runtime (css animations, javascript-driven element changes, dev-tool-injected changes, etc) will not be detected here. I'm not aware of a good / efficient event-driven way to do this outside of the ResizeObserver api. In practice, window-resize-driven canvas resizing should cover the majority of use cases. Users that want to actively poll for element resizes can just do that (or we can build another feature and let people choose based on their specific needs). I also took the chance to make a couple of minor tweaks: * Made the `canvas` window setting available on all platforms. Users shouldn't need to deal with cargo feature selection to support web scenarios. We can just ignore the value on non-web platforms. I added documentation that explains this. * Removed the redundant "initial create windows" handler. With the addition of the code in this pr, the code duplication was untenable. This enables a number of patterns: ## Easy "fullscreen window" mode for the default canvas The "parent element" defaults to the `<body>` element. ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, ..default() }) ``` And CSS: ```css html, body { margin: 0; height: 100%; } ``` ## Fit custom canvas to "wrapper" parent element ```rust app .insert_resource(WindowDescriptor { fit_canvas_to_parent: true, canvas: Some("#bevy".to_string()), ..default() }) ``` And the HTML: ```html <div style="width: 50%; height: 100%"> <canvas id="bevy"></canvas> </div> ```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In retrospect, this makes sense given that we're working around winit by scaling the canvas directly. I don't think we should revert canvas scaling, as it makes the examples visible on mobile / smaller screens and that feels worth it to me.
This seems like it would properly fix our problem, if merged:
rust-windowing/winit#2074
In the interim, we should consider "mitigating quality perception damage". Some ideas:
scaling.mp4
The text was updated successfully, but these errors were encountered: