[SOLVED] Using Iframe as UI window?

Hello,

I’m trying to insert an iframe of a HTML page, where the user can actually paint inside a canvas with certain objects and capture that canvas as an image (the functionality of that page already works). However, it would also be nice if the iframe could be used inside the game (as a standard 2d screen over the camera) and still be interactable, but I’m kinda clueless on how to do such a thing.

Is it possible to render and interact with an iframe inside playCanvas, without needing a second window to be opened with the separate HTML page? There is this project that is very similiar to what I want, but it’s in 3D space and not exactly something that would be in a 2D screen…

I made a project based on that one linked above, I tried using CSS3 renderer but the iframe is not applied on the panel material, yet it already takes over the mouse interaction from the camera if the cursor is over the panel itself.

This is what it’s supposed to render (just a basic HTML)

Link to the project: https://playcanvas.com/editor/scene/1113387

If you are using the CSS3 renderer, it requires a fully transparent camera clear colour and transparent canvas to be enabled on the project settings.

1 Like

If it’s just 2D though, you could add an HTML iframe DOM to the document that is in front of the canvas where the game is.

Turns out turning all the clear colors of the camera to 0 did the work.

Hi, @Abneto the css3renderer is now only support attaching the iframe to 3d plane,but it’s a good idea to support UI element as well.just like 3d plane,you may also want to attach the iframe to an UI Image.
To accomplish this,you can simply calculate the UI in screen space,move and resize the iframe to fit them.
Or you can calculate the 3d plane’s transform base on the UI you want to attach,then move the plane to the front of the camera, make the plane look just like an UI element.In this way,we can apply a smooth translation effect between 3d and 2d just like this:

I am currently working on it :smile:,I’ll let you know if I have any progress.

2 Likes

This does looks really interesting!

However, the way I have done so I can have a proper 2D screen is making an HTML with two iframes, one that hold the paint screen, and one that holds the playcanvas html, and with a class of enabled and disabled at the CSS I can set the display to none in which I dont want to be displayed and vice-versa.

The solution I made was like this one I posted on another thread , where I send a message to the parent website, then make the parent website send a message to playcanvas’ iframe to stop displaying the paint screen and return to the game.

index.html:

<!doctype html>
<html>
<head>
   <script src="js/libs/jquery-3.4.1.min.js"></script>
   <script src="js/index.js"></script>
   <link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- loadscreen is a black panel that shows half a second, cause the paint canvas has to be displayed right away for the canvas object inside to be rendered properly... !-->
    <div id='iframes-container'>
    <iframe id="paintscreen" class='paint-screen enabled' src="https://primo.com.br/clientes/2021/testes/paint/"></iframe>
    <iframe id="loadscreen" class="blackscreen enabled"></iframe>  
    <iframe id="gamescreen" class='playcanvas-game disabled' src="game.html"></iframe>
    </div> 
</body>
</html>

index.js:

var iframe;

$(function(){
    ListenMessages();
    HideLoadingScreen();
})

function ActivatePlaycanvas()
{
    $("#paintscreen").removeClass("enabled");
    $("#paintscreen").addClass("disabled");

    $("#loadscreen").removeClass("enabled");
    $("#loadscreen").addClass("disabled");

    $("#gamescreen").removeClass("disabled");
    $("#gamescreen").addClass("enabled");
}
function DeactivatePlaycanvas()
{
    $("#paintscreen").addClass("enabled");
    $("#paintscreen").removeClass("disabled");

    $("#gamescreen").addClass("disabled");
    $("#gamescreen").removeClass("enabled");
}
function PostMessage(c)
{
    iframe = document.getElementById("gamescreen");
    iframe.contentWindow.postMessage({
        content: c,
    }, "*");
}
function ListenMessages()
{
    //This script stays inside the .js located in the parent website.
    window.onmessage = function(e)
    {
        // alert("message recieved in parent window: " + e.data.content + " from origin: " + e.origin);

        switch(e.data.content)
        {
            case "openPaint":
                {
                    DeactivatePlaycanvas();
                }
                break;
            case "closePaint":
                {
                    PostMessage('closePaint');
                    ActivatePlaycanvas();
                }    
                break;
        }
    }
    console.log("listener for parent window has been registered.");
}

function HideLoadingScreen()
{
    console.log("hiding in progress");
    setTimeout(() =>{
        ActivatePlaycanvas();
    }, 500);
}

and style.css:

.enabled
{
    position: fixed;
    width: 100%;
    height: 100%;
}
.blackscreen
{
    background-color: black;
}
.disabled
{
    display: none;
}
#iframes-container
{
    position:fixed;
    width:100%;
    height:100%;
    margin: 0px;
    top:0px;
    left:0px;
}

Maybe it’s not the most sofisticated, but it seems to work just fine. :sweat_smile:

2 Likes

Have yu achieved proyecting a webpage/html in the proyected wall? I am trying to do the same