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

Allow for manual placement of the canvas element #4479

Closed
AlexanderSchuetz97 opened this issue May 11, 2024 · 4 comments · Fixed by #4561
Closed

Allow for manual placement of the canvas element #4479

AlexanderSchuetz97 opened this issue May 11, 2024 · 4 comments · Fixed by #4561
Assignees
Labels
rerun Desired for Rerun.io web Related to running Egui on the web

Comments

@AlexanderSchuetz97
Copy link

AlexanderSchuetz97 commented May 11, 2024

Is your feature request related to a problem? Please describe.
For Wasm/Web, I want to integrate egui into an existing large single page web application written in javascript/typescript.
egui should only render stuff inside a canvas. Placement of that canvas is very cumbersome as
egui runs code in its update loop that just assumes that egui takes care of the entire screen.

Describe the solution you'd like
An option for me prevent egui from touching the css style of the canvas element at all.
Ideally egui should look at the canvas size in its draw routine in this mode and just "accept" that this is the size it has to use.

Describe alternatives you've considered
Wrap the canvas in a div, and overwrite the css style in the div. This is however very wonky as
if I do not set the size of the div to absolute pixel values for every execution of the update routine the canvas grows larger.
This prevents me from using %width or %height stuff in the div.

My current workaround is not pretty but works:

<div style="height: 500px; width: 500px; position: relative !important;">
    <canvas id="the_canvas_id"></canvas>
</div>

the "position: relative !important" has to be set to overwrite the "position: absolute" that egui sets on the canvas element.
and the sizes have to be set for the update loop to be able to detect. Again if I set the sizes to a percentage then
the canvas will just add 1 pixel each time the update loop is ran. (rounding issue?)

I would prefer to not have to do this at all and just set some flag in WebOptions that placement of the canvas
is "manual" and egui should not mess with the style tag of the canvas at all. Then I could just set all
the stuff on the canvas directly and not abuse a div for this. Plus hopefully the canvas size increase issue would go away
when using %height %width.

Setting the size in the WebOptions::max_size_points is not really helping either since the canvas may move/resize
depending on what the user does and there doesn't appear to be a way of changing these values again after starting
the WebRunner.

Additional context
I am not using trunk, as my goal is to integrate egui into an existing application. I am using wasm-pack. This should not
have any impact tho as the only thing thats different is that the entrypoint is not called main but some other function
that the javascript code calls with the canvas id.
The rest of the "app" code is for now identical to emilk/eframe_template.

@jprochazk
Copy link
Collaborator

jprochazk commented May 24, 2024

There are two reasons why this is happening:

  1. The resize_canvas_to_screen_size function, somewhat confusingly named, attempts to set the width and height CSS properties (not the DOM attributes!) of the canvas element to the size of its parent element rounded to the nearest integer value. This then overwrites any other CSS width/height that may have been applied by users' stylesheets. This is also likely what causes the infinite expansion of the canvas when the parent element has no max width/height.
  2. A bug in the IME/mobile text input handling code. It attempts to shrink the canvas to accomodate the space required by a touchscreen keyboard... by updating the style of the canvas. While well intentioned, the handling of that is better left to the application. I believe it is a bug because the code should not even run at all on non-mobile platforms

First issue should be addressed by:

@AlexanderSchuetz97
Copy link
Author

I dont think this will address my problem. Your still setting the canvas size in your code. (At least as far as I could tell from an inital glance) I asked for an option where the rust code does not touch the canvas dom element at all (other than drawing to it of course). Maybe I am misunderstanding your PR, in that case sorry.

@jprochazk
Copy link
Collaborator

jprochazk commented May 25, 2024

It's setting the width and height DOM attributes, not the style properties. You control the size of the canvas on the page, eframe controls the size of the framebuffer. It has to do that, otherwise you get a stretched image.

Try clicking "play" on this MDN widget: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#result - change the width on the <canvas> and press run. The green square's size doesn't change.

@AlexanderSchuetz97
Copy link
Author

You are correct. I misread this part in the rust code.
I would appreciate your improvment getting merged by the maintainers.

@emilk emilk added this to the Next Major Release milestone May 27, 2024
@emilk emilk added web Related to running Egui on the web rerun Desired for Rerun.io labels May 27, 2024
@jprochazk jprochazk mentioned this issue May 28, 2024
5 tasks
hacknus pushed a commit to hacknus/egui that referenced this issue Oct 30, 2024
- Closes emilk#4060 - no longer aligned
to top
- Closes emilk#4479 - `canvas.style` is
not set anywhere anymore
- Closes emilk#2231 - same as emilk#4060
- Closes emilk#3618 - there is now one
`<input>` per `eframe` app, and it's removed transitively by
`WebRunner::destroy -> AppRunner::drop -> TextAgent::drop`

This PR improves the text agent to make fewer assumptions about how
`egui` is embedded into the page:
- Text agent no longer sets the canvas position
- There is now a text agent for each instance of `WebRunner`
- The input element is now moved to the correct position, so the OS can
display the IME window in the correct place. Before it would typically
be outside of the viewport

The best way to test this is to build & server the web demo locally:
```
scripts/build_demo_web.sh && scripts/start_server.sh
```

Then open the EasyMark editor, and try using IME to input some emojis:
http://localhost:8888/#EasyMarkEditor

To open the emoji keyboard use:
- <kbd>win + .</kbd> on Windows
- <kbd>ctrl + cmd + space</kbd> on Mac

Tested on:
- [x] Windows
- [x] Linux
- [x] MacOS
- [x] Android
- [x] iOS

## Migration guide

The canvas no longer controls its own size/position on the page. This
means that those properties can now be controlled entirely via HTML and
CSS, and multiple separate `eframe` apps can coexist better on a single
page.

To match the old behavior, set the `canvas` width and height to 100% of
the `body` element:

```html
<html>
  <body>
    <canvas></canvas>
  </body>
</html>
```

```css
/* remove default margins and use full viewport */
html, body {
  margin: 0;
  width: 100%;
  height: 100%;
}

canvas {
  /* match parent element size */
  width: 100%;
  height: 100%;
}
```

Note that there is no need to set `position: absolute`/`left: 50%;
transform: translateX(-50%)`/etc., and setting those properties may
poorly affect the sharpness of `egui`-rendered text.

Because `eframe` no longer updates the canvas style in any way, it also
means that on mobile, the canvas no longer collapses upwards to make
space for a mobile keyboard. This should be solved in other ways:
emilk#4572
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rerun Desired for Rerun.io web Related to running Egui on the web
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants