Cem's UI HTML elements don't work with rendering fill mode keep aspect ratio

@yaustar Curious if you know why this would break if you are using the “Keep aspect ratio” option for your fill mode under the rendering settings. Not sure how to calculate the edge of the viewport in relation to the document off the top of my head but I suspect it has to do with that. You can just barely see in the screenshot below, it says email on the top left corner of the screen outside of the PlayCanvas viewport while the element sits within the viewport.

Anyone have any thoughts on this?

This is using Cem’s UI components system here PlayCanvas UI Components

It breaks because the HTML elements positioning doesn’t take the canvas html element position into account. You will need to modify the library so that it also adds the canvas element offset in the viewport to the positioning of the html elements.

In a published build, you can find out how the canvas is positioned in __start__.js for this fill mode

Okay I fixed the offset issue. How would you fix the scaling issue? You can see in the video, the offset works fine now. Here is the video (i only fixed the text input… i have not applied anything to the other elements like the checkbox):

Here is the current code fix for anyone that is interested in the offset fix:

Input.prototype.updateStyle = function() {
    if(this.entity.element.screenCorners){
        var position = this.entity.element.screenCorners;
        var devicePixelRatio = this.app.graphicsDevice.maxPixelRatio;
        // offset fix
        this.element.style.left = ((position[0].x / devicePixelRatio + Math.floor((window.innerWidth - canvas.clientWidth) / 2) )) + 'px';
        this.element.style.bottom = ((position[0].y / devicePixelRatio + Math.floor((window.innerHeight - canvas.clientHeight) / 2) )) + 'px';

        this.element.style.width = ((position[2].x - position[0].x) / devicePixelRatio ) + 'px';
        this.element.style.height = ((position[2].y - position[0].y) / devicePixelRatio ) + 'px';
    }
};

Thanks in advance

2 Likes

Oh actually I think I may see the issue with the scaling. It can only be based on width or height, not both on the script’s parameters. So without explicitly setting it at the pixel amount, I’m not sure this can be done quite as well as the offset can be calculated.

Just going off width will probably work though for my needs.

From the video, it still looks like some offsets/calculations are still off :thinking:

I’ve forked the original project and made changes to the slider and checkbox as examples: PlayCanvas | HTML5 Game Engine

Kapture 2022-06-09 at 13.50.10

Relevant code:

Slider.prototype.updateStyle = function() {
    if(this.entity.element.screenCorners){
        var position = this.entity.element.screenCorners;

        var devicePixelRatio = this.app.graphicsDevice.maxPixelRatio;
        // Offset the position by the canvas position
        var canvasRect = this.app.graphicsDevice.canvas.getBoundingClientRect();
        var left = (position[0].x / devicePixelRatio) + canvasRect.x;
        var right = (position[2].x / devicePixelRatio) + canvasRect.x;
        var bottom = (position[0].y / devicePixelRatio) + canvasRect.y;
        var top = (position[2].y / devicePixelRatio) + canvasRect.y;

        this.element.style.left = (left) + 'px';
        this.element.style.bottom = (bottom) + 'px';

        this.element.style.width = ((right - left)) + 'px';
        this.element.style.height = ((top - bottom)) + 'px';
    }
};

Edit: I see you’ve basically done the same thing and now I know what you mean by scaling of the HTML elements :thinking:

Not sure what to do about that as that is more to do with the styling of the HTML element.