How to make a loading screen in three.js?

前端 未结 2 1569
粉色の甜心
粉色の甜心 2021-02-01 20:21

I have a large amount of textures and models to load into my project. I am trying to show a progress bars while everything is loading. I think the LoadingManager

相关标签:
2条回答
  • 2021-02-01 21:02

    LoadingManager Update

    as @2pha points out, the below is pointless as THREE already implements a loading Manager - the below will remain for posterity, but have a look at this:

    https://threejs.org/docs/?q=loading#api/loaders/managers/LoadingManager

    Easy-peasy:

    var progress = document.createElement('div');
    var progressBar = document.createElement('div');
    
    progress.appendChild(progressBar);
    
    document.body.appendChild(progress);
    
    var manager = new THREE.LoadingManager();
    manager.onProgress = function ( item, loaded, total ) {
      progressBar.style.width = (loaded / total * 100) + '%';
    };
    
    function addRandomPlaceHoldItImage(){
      var r = Math.round(Math.random() * 4000);
      new THREE.ImageLoader(manager).load('http://placehold.it/' + r + 'x' + r);
    }
    
    for(var i = 0; i < 10; i++) addRandomPlaceHoldItImage();
    div {
      width: 200px;
      height: 20px;
      background: #000;
      border: 2px solid #000;
    }
    div > div {
      width: 200px;
      height: 20px;
      background: red;
      border: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"></script>

    Original Post

    Something like the below should do your trick - mind that I have just quickly tested it and there is probably a couple of improvements to make (including using the progress callback in THREE js). I haven't fully refined it either, but it gives you a general implementation of how to do this. I also haven't implemented an error handler, etc... Those are things that take a bit longer to make, but you get the general idea.

    You add new types of loaders (that conform to the type + Loader in THREE) and their sources, then initiating the load by simply calling load.

    Hope it helps.

    (I also made a random function to get some random images from placehold.it since using the same results over and over means that caching kills the server.)

    function LoaderProgress(callback){
      this.length 	  = -1;
      this.complete   = 0;
      this.domElement = document.createElement('div');
      this.progress	  = document.createElement('div');
      
      this.domElement.appendChild(this.progress);
      this.domElement.className = 'loader-progress-wrapper';
      this.progress.className   = 'loader-progress-progress';
      this.progress.style.width = '0%';
      
      this.callback = callback || function(){};
    }
    LoaderProgress.prototype.add = function(type, src){
      var result = this[++this.length] = {
        loader: new THREE[type + 'Loader'],
        complete: false,
        source: src
      };
      return result;
    }
    LoaderProgress.prototype.load = function(){
      this.complete = 0;
      for(var i = 0; i < this.length; i++){
        var current = this[i];
        if(!current.complete){
          current.loader.load(this[i].source, function(result){
            current.complete = result;
            this.complete++;
            this.update();
          }.bind(this));
        }
      }
      return this;
    }
    LoaderProgress.prototype.update = function(a){
      var progress = this.complete / this.length;
      this.progress.style.width = (progress * 100) + '%';
      if(progress === 1) this.callback(this);
      console.log(progress);
      return progress;
    }
    
    var loader = new LoaderProgress(function(){
      // Execute code that needfs the loaded elements here
      alert('All are loaded');
    });
    
    document.body.appendChild(loader.domElement);
    
    function addRandomPlaceHoldItImage(){
      var r = Math.round(Math.random() * 4000);
      loader.add('Image', 'http://placehold.it/' + r + 'x' + r);
    }
    
    for(var i = 0; i < 10; i++)
      addRandomPlaceHoldItImage();
    
    loader.load();
    .loader-progress-wrapper {
      width: 200px;
      height: 20px;
      background: #000;
      border: 2px solid #000;
    }
    .loader-progress-progress {
      width: 200px;
      height: 20px;
      background: red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"></script>

    0 讨论(0)
  • 2021-02-01 21:27

    Docs: http://threejs.org/docs/#Reference/Loaders/TextureLoader

    Example: http://threejs.org/examples/#webgl_loader_obj

    Code:

      var sphereMaterial = new THREE.MeshBasicMaterial();
    
      var onProgress = function ( xhr ) {
        if ( xhr.lengthComputable ) {
          var percentComplete = xhr.loaded / xhr.total * 100;
          console.log( Math.round(percentComplete, 2) + '% downloaded' );
        }
      };
    
      var loader = new THREE.TextureLoader();
      var texture = loader.load("___4MB_IMAGE.JPG___", undefined, onProgress);
      sphereMaterial.map = texture;
    

    It solves a similar problem I had - 4MB texture that takes some time to load over the wire...

    0 讨论(0)
提交回复
热议问题