[SOLVED] Resizing application canvas in self-hosted


We are trying to host the applicaton on our server, with a UI that is not in the canvas itself. There is a slight issue however.

When we are using a layout of 85% - 15% width for 2 divs, and place an iFrame in the first larger div, then point our build’s index.html to this iFrame, the aspect ratio is preserved, the app is present, and via postMessage we can communicate with the application.

This however comes with a performance overhead. Our custom UI is just 2 buttons in CSS/HTML, nothing else. When testing on a weaker device (eg.: mobile phone) the iFrame site is really laggy. If accessing the app’s index.html directly, the lag completely goes away.

So we came to the conclusion of placing our UI and stuff in the app’s index.html, instead of putting that in an iFrame. However we need to resize the canvas itself. When we do a width param on the canvas, or we move the canvas by id into a sized div, the application aspect ratio is not preserved, and the scene is squished from the sides.

How do we resize the canvas, or put it in a custom div, while preserving the aspect ratio?


In the config.json, there is a parameter called “fillMode”, when setting this to “KEEP_ASPECT” instead of “FILL_WINDOW” nothing happens, the scene is still squished. When changing the class directly to KEEP_ASPECT on the canvas, the width becomes 100% instead of the parent div size, thus the size is wrong.

Just to check, do you want to be able to control the size of the canvas via CSS/HTML rules and PlayCanvas to not resize the canvas in the engine?

1 Like

To be honest, the method makes no difference. What we want to achieve is for the app to look like it’s in an iFrame.

Eg.: Create a DIV with whatever size and aspect ratio, and put the canvas in this DIV, while maintaining the aspect ratio of the application.

In which case, I generally prefer to have the canvas CSS/HTML be the ‘controller’ of size.

To do this (from memory) is to set the fill mode to ‘NONE’ and change __start__.js reflow to:

var reflow=function() {

An alternative method can be found here: Embedding PlayCanvas into a webpage without iframe

Neither of these are well tested and I’m wondering if there will be issues with screenToWorld calls.

1 Like

So I have checked and used both your method and the link. The final solution is

  • Use your code for the reflow() function
  • Edit start.js to inject canvas into the custom div directly instead of the body
  • Modify styles.css to make canvas position relative instead of absolute
  • Change margin from auto to “0 auto” on KEEP_ASPECT class
  • Set KEEP_ASPECT as fill mode in the config.json
1 Like

Sweet, looks like you didn’t have to patch the engine at all which is always good

There is one slight issue with this method, that I’m just gonna let go for now.

Basically as it’s setting the resolution for the aspect ratio, if either the width or the height is off, then on the sides of the app, or on the bottom and the top, there is an area, where the background is showing through, so clicking those areas will not rotate the scene, etc. Weirder the resolution, the more apparent. For example:

On my 16:9 screen it’s about 1-1cm on each side. On my 21:9 screen it’s 5-5 centimeters on each side.

I see that you have a github repo that resizes the canvas correctly, so I’m gonna check that out and implement it in my own app, because that seems to solve this issue.

Using your repo, I have implemented an engine-fix and some additional modifications. Fill mode NONE and 100% height on the body, now no matter how weird I scale the window, it’s never squished and all parts of the screen are actually controlling the canvas.

Might be related to the fill mode setting as the resize canvas function in the engine will resize the canvas.

If you are using Fill Mode NONE, then the engine patch shouldn’t be necessary as it doesn’t go down that code branch.

So basically all we need to do is pop this in the reflow function of start.js

app.resizeCanvas(wrapper.clientWidth, wrapper.clientHeight);

and done?

As long as the Fill Mode is None, I believe you can do app.resizeCanvas(); and the engine won’t try to resize the canvas. If that doesn’t work, go back to the patch as that’s ‘known’ to work :sweat_smile:

1 Like

Well it’s working nice and dandy, even on mobile, and different orientations, so I’m happy with it. Thank you for the help!