Search code examples
javascriptvideoloadaframevirtual-reality

Aframe splashscreen if videopsphere loads


Hiho Community,

i try to show a splashscreen if my videosphere loads. I use this code -> set a loading animation with a-frame for loading a splash before the scene and it works perfect, but i need to let my videos have the attribute preload so if i start them they need some time to load too and there should the splashscreen pops up again. Some ideas (maybe a second listener which says: show splashscreen if video loading)?.

HTML:

<body>
 <div id="splash">
   <div class="loading"></div>
 </div>

 <a-scene>
   <a-assets>
     <video id="vid" loop="false" preload="none" 
      crossorigin="anonymous">
          <source type="video/mp4" src="..." />
     </video>
   </a-assets>

   <a-videosphere src="#vid"></a-videosphere>

 </a-scene>
</body>

CSS:

#splash {
  position: absolute;

  display: flex;
  align-items: center;
  justify-content: center;

  top: 0;
  bottom: 0;
  left: 0;
  right: 0;

  width: 200px;
  height: 200px;

  margin: auto;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.loading {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 0.25rem solid rgba(255, 255, 255, 0.2);
  border-top-color: white;
  animation: spin 1s infinite linear;
}

javascript:

document.addEventListener('DOMContentLoaded', function() {
    var scene = document.querySelector('a-scene');
    var splash = document.querySelector('#splash');
    scene.addEventListener('loaded', function (e) {
        splash.style.display = 'none';
    });
});

Solution

  • There are many ways to go about this with varying levels of complexity. The trouble with video, from my experience, is that browsers rarely completely preload the video; they only load until a certain point until the user watches the video of the play head moves.

    I noticed that you have set preload="none" on your video; I would consider changing this to preload="auto".

    If you have a network connection, the simplest way I can think of would be to check against the video's readyState at certain intervals. I've tried doing so on the loadeddata event with inconsistent results, so I can't recommend that.

    https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState

    You can try something like this (preferably within an A-Frame system or component):

    // The video element
    var video = document.querySelector('#vid');
    
    // Define interval in milliseconds
    var interval = 1000;
    
    // Check readyState immediately
    checkVidState();
    
    // Function to detect if video has enough data to play
    function checkVidState() {
    
      if (video.readyState === 4) {
        removeSplash();
        return true;
      }
    
      // If readyState !== 4, check again at set interval
      setTimeout(checkVidState, interval);
      return false;
    
    }
    
    // Function for removing splash
    function removeSplash() {
      // Logic for removing splash here...
    }
    

    If you need to be able to do this for multiple videos and aren't using A-Frame components, you can define the function as follows:

    function checkVidState( video, interval ) {
      // Same inner code as above
    }
    

    You just need to pass the video element and the check interval value.

    Then call them for each video element or loop through an array of them:

    checkVideoState( video1, interval ); // or time in milleseconds
    checkVideoState( video2, interval );
    . . .