p5.js Example (height: auto)
This example has iframe style set as:
width: 100%; height: auto; overflow: hidden;The iframe will render at the width of it's parent. The canvas inside will adjust to it's width, and render at it's full height depending on the sketch resolution. (180x120)
Now I can then use a function in JS as follows:
function resize(iframe) { iframe.height = iframe.contentWindow.document.body.scrollHeight + "px"; iframe.contentWindow.addEventListener('resize', () => { iframe.height = iframe.contentWindow.document.body.scrollHeight + "px"; }); }Which will resize the iframe to the rendered height and add an event listener for resize.
p5.js Example (auto-resize)
If I apply the resize function in the iframe's onload event:
<iframe src="simple-life-p5js.html" onload="resize(this);">The initial canvas size is calculated based on the width, and not on the height, so it will render the full canvas and I can resize to the scrollHeight of the body.
In order to do that, inside the embedded src for the iframe I made sure the canvas, html and body have this style:
html, body { width: 100%; padding: 0; margin: 0; } main, .p5Canvas { width: 100% !important; height: 100% !important; display: block; image-rendering: pixelated; // optional but useful }But as you can see by inspecting, the canvas width and height attributes themselves are the ones I actually set in my project (180 x 120), so I know my internal resolution and I can scale my canvas and let the browser do it's thing. (image-rendering: pixelated; works wonders here)
This iframe is now responsive! As well as the document with the canvas inside it! You can try resizing your browser or adjusting the parents width, and it will display correctly.
ebiten Example (height: auto)
When embedding an ebiten project (this one is also 180x120), the iframe's src document has the html and body set to full height, which in turn calculates the width and then sets the canvas size of the iframe to the width of the viewport! Not the width of my project! (returning the outside size in Layout will just move the tiny canvas to the upper left corner)
And because the height is used to initialize the canvas (instead of the width), if I use the resize function, the program will exit with status code 2 as it cannot initialize the canvas with height 0.
In this case I ALWAYS have to know before hand the exact width and height of the project, and even then, I need to calculate the height to preserve display ratio. The canvas width and height attributes need to ALWAYS be the ones defined inside the project width setWindowSize or by the Layout function to avoid surprises. And then scale the canvas appropriately using the canvas style with: width and height both to 100%.
ebiten Example (fixed size)
Of course I can always set the fixed width and height attributes, but then I can't make it responsive. Because the canvas width will scale according to the content, but the height can't. And I always need to know before hand what size the project is, which defeats the purpose in my blog of using Hugo shortcodes to embed projects easily, and does not let the browser do it's job by resizing the canvas itself.
Is there a way or hack to make ebiten projects auto-resize based on content width?
Ebiten Modified Example (solution)
In this example, the iframe has no width or height set, the onload function is called with the parent id and aspect ratio. And looks like this:
function resizeEbiten(iframe, parentId, aspectRatio) { let parent = document.getElementById(parentId); let w = parent.clientWidth; iframe.width = w; iframe.height = w * aspectRatio; iframe.contentWindow.addEventListener('resize', () => { let w = parent.clientWidth; iframe.width = w; iframe.height = w * aspectRatio; }); }This way, as long as you know the aspectRatio the width of the iframe is taken from it's parent and it's height is dynamically calculated based on the aspectRatio.
Try resizing the browser window to see it resize correctly. While maintaining fixes logical screen size