Animated Loading Screen with sounds

is there a way/script to change the canvas loading screen with a video or gif and once the loading screen starts it plays a sound

Yes. Ideally you have the image/video hosted from an external source otherwise you would have to wait till the app registry is loaded until you can get the URL of the asset.

See this page for more details: https://developer.playcanvas.com/en/user-manual/designer/loading-screen/

In terms of playing a sound, you would have to use the WebAudio API directly as it is a plain HTML page.

Alternatively, you can have a very simple app preloader and create a more ‘rich’ loader in the PlayCanvas app and that will allow you do use the Engine to play sounds, play animations etc. eg https://developer.playcanvas.com/en/tutorials/load-assets-with-a-progress-bar/

1 Like

So what would be a example script of that do i need to put the gif file in the script?

Or i just need a url of the gif

An animated gif url added to an html image element will work just fine.

so like this?

// Use an image from the assets in the project via the asset registry
// More information: http://developer.playcanvas.com/en/api/pc.AssetRegistry.html
app.on('preload:start', function() {
    var splash = document.getElementById('application-splash');
    
    var logoAsset = app.assets.find('https://i.kym-cdn.com/photos/images/newsfeed/000/528/363/2f0.gif');

heres the whole script

pc.script.createLoadingScreen(function (app) {
var showSplash = function () {
// splash wrapper
var wrapper = document.createElement(‘div’);
wrapper.id = ‘application-splash-wrapper’;
document.body.appendChild(wrapper);

    // splash
    var splash = document.createElement('div');
    splash.id = 'application-splash';
    wrapper.appendChild(splash);
    splash.style.display = 'none';
    
    var container = document.createElement('div');
    container.id = 'progress-bar-container';
    splash.appendChild(container);

    var bar = document.createElement('div');
    bar.id = 'progress-bar';
    container.appendChild(bar);

};

var hideSplash = function () {
    var splash = document.getElementById('application-splash-wrapper');
    splash.parentElement.removeChild(splash);
};

var setProgress = function (value) {
    var bar = document.getElementById('progress-bar');
    if(bar) {
        value = Math.min(1, Math.max(0, value));
        bar.style.width = value * 100 + '%';
    }
};

var createCss = function () {
    var css = [
        'body {',
        '    background-color: #283538;',
        '}',

        '#application-splash-wrapper {',
        '    position: absolute;',
        '    top: 0;',
        '    left: 0;',
        '    height: 100%;',
        '    width: 100%;',
        '    background-color: #283538;',
        '}',

        '#application-splash {',
        '    position: absolute;',
        '    top: calc(50% - 132px);',
        '    width: 264px;',
        '    left: calc(50% - 132px);',
        '}',

        '#application-splash img {',
        '    width: 100%;',
        '}',

        '#progress-bar-container {',
        '    margin: 20px auto 0 auto;',
        '    height: 2px;',
        '    width: 100%;',
        '    background-color: #1d292c;',
        '}',

        '#progress-bar {',
        '    width: 0%;',
        '    height: 100%;',
        '    background-color: #f60;',
        '}',
        '@media (max-width: 480px) {',
        '    #application-splash {',
        '        width: 170px;',
        '        left: calc(50% - 85px);',
        '    }',
        '}'
    ].join("\n");

    var style = document.createElement('style');
    style.type = 'text/css';
    if (style.styleSheet) {
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }

    document.head.appendChild(style);
};


createCss();

showSplash();

// Use an image from the assets in the project via the asset registry
// More information: http://developer.playcanvas.com/en/api/pc.AssetRegistry.html
app.on('preload:start', function() {
    var splash = document.getElementById('application-splash');
    
    var logoAsset = app.assets.find('https://i.kym-cdn.com/photos/images/newsfeed/000/528/363/2f0.gif');
    
    if (logoAsset) {
        var logo = document.createElement('img');    
        logo.src = logoAsset.getFileUrl();

        // Insert DOM before the progress bar
        if (splash.childNodes.length > 0) {
            splash.insertBefore(logo, splash.childNodes[0]);
        } else {
            splash.appendChild(logo);
        }
        
        logo.onload = function () {
            splash.style.display = 'block';
        };
    }
});
    
app.on('preload:end', function () {
    app.off('preload:progress');
});
app.on('preload:progress', setProgress);
app.on('start', hideSplash);

});

@Leonidas

Hi @DerpySlurrpe,

If you are hosting the remote gif in your server, no need to search in the Playcanvas registry.

Just replace the current img logo element, src attribute. Here is an example from the default Playcanvas splash screen:

        var logo = document.createElement('img');
        logo.src = 'https://i.kym-cdn.com/photos/images/newsfeed/000/528/363/2f0.gif';
        splash.appendChild(logo);
        logo.onload = function () {
            splash.style.display = 'block';
        };

@Leonidas is there a way also to resize it in any way and move it

Well, since it’s an HTML element you can resize/move it using regular CSS:

            '#application-splash img {',
            '    width: 50%;',
            '}',

Hey there,

sorry for bumping this topic but I have a similar question. I want to access a video asset for the loading screen of my playcanvas hosted project (like https://s3-eu-west-1.amazonaws.com/apps.playcanvas.com/TSHvIaSK/files/assets/51186527/1/Intro.mp4).

I tried it like that, but this doesn’t seem to work:

pc.script.createLoadingScreen(function (app) {
    var showSplash = function () {
        
        // Find CDN URL
        var introVideo = app.assets.find("Intro.mp4");
    
        if (introVideo) {
            var introVideoUrl = introVideo.getFileUrl();
            console.log('#D URL:' + introVideoUrl);
        }

What is the best pratice for that?

Full Script:

pc.script.createLoadingScreen(function (app) {
    var showSplash = function () {
        
        // Find CDN URL
        var introVideo = app.assets.find("Intro.mp4");
    
        if (introVideo) {
            var introVideoUrl = introVideo.getFileUrl();
            console.log('#D URL:' + introVideoUrl);
        }
            
        //var logo = document.createElement('img');    
        //logo.src = logoAsset.getFileUrl();
        
        // splash wrapper
        var wrapper = document.createElement('div');
        wrapper.id = 'application-splash-wrapper';
        document.body.appendChild(wrapper);

        // videodiv
        var videodiv = document.createElement('div');
        videodiv.id = 'application-video';
        wrapper.appendChild(videodiv);
        //videodiv.style.display = 'block';

        // splash
        var splash = document.createElement('div');
        splash.id = 'application-splash';
        
        wrapper.appendChild(splash);
        splash.style.display = 'none'; 
        splash.style.zIndex = '-1';

        
        var logo = document.createElement('img');
        logo.src = 'https://www.rl-intermix.com/02_TECHTEST/loading.png';
        splash.appendChild(logo);
        logo.onload = function () {
            splash.style.display = 'block';
        };
        
        var container = document.createElement('div');
        container.id = 'progress-bar-container';
        splash.appendChild(container);

        var bar = document.createElement('div');
        bar.id = 'progress-bar';
        container.appendChild(bar);
        
        var introvideo = document.createElement('video');
        introvideo.src = 'https://www.rl-intermix.com/02_TECHTEST/210517_Nico_1_EN_720p.mp4';
        //introvideo.setAttribute('controls', 'controls');
        introvideo.setAttribute('playsinline', '');
        introvideo.setAttribute('poster', 'https://www.rl-intermix.com/02_TECHTEST/intro_poster.jpg');


        videodiv.appendChild(introvideo);
        introvideo.addEventListener("ended", function(e) {
            videoready = true;
            hideVideo();    
            frontSplash();            
            app.fire('preloader:check');            
        });
    
/*        introvideo.onload = function () {
            videodiv.style.display = 'block';
        };*/        

        // svg playbutton
        var buttonsdiv = document.createElement('div');
        buttonsdiv.id = 'player-buttons';
        videodiv.appendChild(buttonsdiv);
        
        var play_image = document.createElement("img");
        play_image.setAttribute("src", "https://www.rl-intermix.com/02_TECHTEST/Play_HotSpotStyle.png");
        buttonsdiv.appendChild(play_image);
        
        buttonsdiv.addEventListener("click", function(e) {
            //console.log('play pressed');
              if (introvideo.paused) {
                introvideo.play(); 
                play_image.style.display = "none";
              }
              else {
                introvideo.pause();
                play_image.style.display = "block";
              }
        });            
        
     
        
    };

    var hideSplash = function () {
        var splash = document.getElementById('application-splash-wrapper');
        splash.parentElement.removeChild(splash);
    };
    
    var frontSplash = function () {
        var splash = document.getElementById('application-splash');
        splash.style.zIndex = '0';
    };
    
    var hideVideo = function () {
        var videodiv_var = document.getElementById('application-video');
        videodiv_var.parentElement.removeChild(videodiv_var);
    };
    
    var setProgress = function (value) {
        var bar = document.getElementById('progress-bar');
        if(bar) {
            value = Math.min(1, Math.max(0, value));
            bar.style.width = value * 100 + '%';
        }
    };

    var createCss = function () {
        var css = [

            '#application-splash-wrapper {',
            '    position: absolute;',
            '    top: 0;',
            '    left: 0;',
            '    height: 100%;',
            '    width: 100%;',
            '    background-color: #000000;',
            '}',
            '',
            '#application-splash {',
            '    position: absolute;',
            '    top: calc(50% - 132px);',
            '    width: 264px;',
            '    left: calc(50% - 132px);',
            '}',
            '',            
            '',
            '#application-video {',
            'position: relative;',
            'margin: 0 !important;',
            'width: 100%;',
            'height: 100%;',
            'display: flex;',
            'justify-content: center;',
            'align-items: center;',
            'overflow: hidden;',
            '}',
            '',
            
            '#player-buttons {',
            'position: absolute;',
            'z-index: 10;',
            'border-style: none;',
            'border-color: white;',
            '}',
            '',           
            '#application-splash img {',
            '    width: 100%;',
            '}',
            '#application-video video {',
            '    width: 100%;',
            '}',
            '',
            '#application-video img {',
            '    width: 23vw;',
            '}',
            '',            
            '#progress-bar-container {',
            '    margin: 20px auto 0 auto;',
            '    height: 2px;',
            '    width: 100%;',
            '    background-color: #1d292c;',
            '}',
            '',
            '#progress-bar {',
            '    width: 0%;',
            '    height: 100%;',
            '    background-color: #f60;',
            '}',
            '',
            '@media (max-width: 480px) {',
            '    #application-splash {',
            '        width: 170px;',
            '        left: calc(50% - 85px);',
            '    }',
            '}'
        ].join('\n');

        var style = document.createElement('style');
        style.type = 'text/css';
        if (style.styleSheet) {
            style.styleSheet.cssText = css;
        } else {
            style.appendChild(document.createTextNode(css));
        }

        document.head.appendChild(style);
    };

    var videoready = false;
    var gameloaded = false;
    
    createCss();
    showSplash();

    app.on('preload:end', function () {
        //console.log('Preload:end');
        app.off('preload:progress');
    });
    app.on('preload:progress', setProgress);
    //app.on('start', hideSplash);
    
    app.on('preloader:check', function () {
        if ((videoready === true) && (gameloaded === true)){
            //console.log('!!!! 1 ((videoready === true) && (gameloaded === true))');  
            //console.log('videoready: ' + videoready + ' gameloaded: ' + gameloaded);

            hideSplash();
            app.fire('preloader:application:start');
            
            setTimeout(function() {
                app.fire('preloader:application:start');                
            }, 100);
            setTimeout(function() {
                app.fire('preloader:application:start');                
            }, 1000);
            setTimeout(function() {
                app.fire('preloader:application:start');                
            }, 10000);
            setTimeout(function() {
                app.fire('preloader:application:start');                
            }, 60000);
        }
    });
    
    app.on('start', function () {
        gameloaded = true;
        //console.log('!!!! 2 start');
        app.fire('preloader:check');
    });
});

Can you show an example project please that can be looked at?

Is this accesible?
https://playcanvas.com/editor/scene/1193908

I want to replace the Intro Video (now hosted on my personal server) with the “Intro.mp4” of the playcanvas project (video/Intro.mp4). In the loadingscreen.js script, I started at line 4 to access the actual CDN URL, but for some reason the line 8 console.log('#D URL ' + introVideo.getFileUrl()); is never executed… What I’m doing wrong?

Thanks
Martin

1 Like

Had a look, the issue is that the assets haven’t been added to the registry yet when the splash screen is created so you can’t access the video asset via the registry until later in the initialisation.

If you really must use a video asset rather than an external video URL, listen for the add event on the registry when the splash screen is created: AssetRegistry | PlayCanvas API Reference

And add the video to the preloader screen on the event callback.

Forgot to mention, if you do it this way, be warned it is not predictable when the video is shown as there may be blocking HTTP requests already in the browser from loading assets prior to the video asset being added.

I recommend using a URL to the video file instead like you have done here.

Thanks a lot for your precise and timely support! Will just use a URL…