0

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';
    });
});
Delidragon
  • 165
  • 4
  • 17

2 Answers2

1

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 );
. . .
Dan S.
  • 331
  • 1
  • 7
  • thx i try it. I need to let preload = none because i dont want that people with phone use there hole data for my videos. They are 4k 360 degree videos so pretty heavy stuff. – Delidragon Sep 10 '18 at 07:51
  • it works but just once i guess i need this as listener – Delidragon Sep 10 '18 at 08:27
  • for what is return true? Can it be that i need to set something first on false to repeat this behaviour? – Delidragon Sep 10 '18 at 08:33
  • oh yeah looks like return true makes that it cant be repeated so i just removed the line and now it works without listener thanks a lot everthings nice now – Delidragon Sep 10 '18 at 08:35
  • Understood about the mobile data; however, as I stated in the answer, browsers do not fully load videos even when `preload="auto"` is set; they only load as much data as needed to keep playing without interruption. So, essentially, you'd just be loading enough data for each video to get things started. – Dan S. Sep 11 '18 at 21:24
  • 1
    Yes, `return true;` is so the function returns before setting another timeout to repeat the check. If you remove it, it will keep checking constantly even after the video is loaded, so removing it may not be the best option. The value that is returned isn't really important in this case; you could use `return`, `return false`, etc. I only chose `return true;` in case you wanted to check `checkVidState()` for a value. Example: `if ( checkVidState() ) { //do stuff; }` I'll add `return false;` if the check fails to make this more obvious. – Dan S. Sep 11 '18 at 21:27
  • Updated answer with solution for checking multiple videos. – Dan S. Sep 11 '18 at 21:44
0

like this ? @Dan S.

  // The video element
  var videoEl_1 = document.querySelector('#intro');
  var videoEl_2 = document.querySelector('#dach');
  var videoEl_3 = document.querySelector('#door');
  var videoEl_4 = document.querySelector('#grube');
  var videoEl_5 = document.querySelector('#schleifen');
  var videoEl_6 = document.querySelector('#outro');

  // Define interval in milliseconds
  var interval = 1000;

function checkVidState( videoEl_1, interval ) {

  // Check readyState immediately
  checkVidState();

  // Function to detect if video has enough data to play
  function checkVidState() {

    if (videoEl_1.readyState === 4) {
      removeSplash_2();
      return true;
    }

    /*if (videoEl_2.readyState === 4) {
      removeSplash_2();
      return true;
    }

    if (videoEl_3.readyState === 4) {
      removeSplash_2();
      return true;
    }

    if (videoEl_4.readyState === 4) {
      removeSplash_2();
      return true;
    }

    if (videoEl_5.readyState === 4) {
      removeSplash_2();
      return true;
    }

    if (videoEl_6.readyState === 4) {
      removeSplash_2();
      return true;
    }*/

    // If readyState !== 4, check again at set interval
    setTimeout(checkVidState, interval);
    return false;
  }

  // Function for removing splash
  function removeSplash_2() {
    var splash_2 = document.querySelector('#splash_2');
    splash_2.style.display = 'none';
  }
}

<a-box onclick="checkVideoState( videoEl_1, interval );"></a-box>
<a-box onclick="checkVideoState( videoEl_2, interval );"></a-box>
...
Delidragon
  • 165
  • 4
  • 17