简体   繁体   English

如何在three.js中制作加载屏幕?

[英]How to make a loading screen in three.js?

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 does just what I need as it tracks the progress of all loaded assets. 我认为LoadingManager正好能够跟踪所有已加载资产的进度。

I'm using the JSONLoader and TextureLoader. 我正在使用JSONLoader和TextureLoader。

If anyone could show me how to do implement this in the example code would be awesome. 如果有人可以告诉我如何实现这个示例代码将是非常棒的。

在此输入图像描述

 var camera, scene, renderer; init(); animate(); function init() { camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000); camera.position.z = 400; scene = new THREE.Scene(); // Load Textures var modeltexture1 = new THREE.TextureLoader().load('modeltexture1.jpg'); var modeltexture2 = new THREE.TextureLoader().load('modeltexture2.jpg'); var modeltexture3 = new THREE.TextureLoader().load('modeltexture3.jpg'); var modeltexture4 = new THREE.TextureLoader().load('modeltexture4.jpg'); // Materials var material = { "texture1": new THREE.MeshPhongMaterial({ map: modeltexture1 }), "texture2": new THREE.MeshPhongMaterial({ map: modeltexture2 }), "texture3": new THREE.MeshPhongMaterial({ map: modeltexture3 }), "texture4": new THREE.MeshPhongMaterial({ map: modeltexture4 }), } // Lights scene.add(new THREE.AmbientLight(0xcccccc)); pointLight = new THREE.PointLight(0xff4400, 5, 30); pointLight.position.set(5, 0, 0); scene.add(pointLight); var loader = new THREE.JSONLoader(); // Model1 var model1 = new THREE.Object3D; scene.add(model1); loader.load("model1.js", function(geometry) { var mainmodel1 = new THREE.Mesh(geometry, material["texture1"]); model1.add(mainmodel1); }); // Model2 var model2 = new THREE.Object3D; scene.add(model2); loader.load("model2.js", function(geometry) { var mainmodel2 = new THREE.Mesh(geometry, material["texture2"]); model2.add(mainmodel2); }); // Model3 var model3 = new THREE.Object3D; scene.add(model3); loader.load("model3.js", function(geometry) { var mainmodel3 = new THREE.Mesh(geometry, material["texture3"]); model3.add(mainmodel3); }); // Model4 var model4 = new THREE.Object3D; scene.add(model4); loader.load("model4.js", function(geometry) { var mainmodel4 = new THREE.Mesh(geometry, material["texture4"]); model4.add(mainmodel4); }); renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // window.addEventListener('resize', onWindowResize, false); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } 
 body { margin: 0; } canvas { width: 100%; height: 100% } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"></script> 

LoadingManager Update LoadingManager更新

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: 正如@ 2pha指出的那样,下面的内容毫无意义,因为THREE已经实现了一个加载管理器 - 以下内容将留给后代,但看看这个:

https://threejs.org/docs/?q=loading#api/loaders/managers/LoadingManager 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). 像下面这样的东西应该做你的伎俩 - 介意我刚刚快速测试它,并且可能有一些改进(包括在三个js中使用progress回调)。 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 . 您可以添加新类型的加载器(符合THREE中的type + Loader )及其来源,然后通过简单地调用load启动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.) (我还做了一个随机函数来从placehold.it获取一些随机图像,因为反复使用相同的结果意味着缓存会杀死服务器。)

 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> 

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

Example: http://threejs.org/examples/#webgl_loader_obj 示例: 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... 它解决了我遇到的类似问题 - 4MB纹理,需要一些时间来加载电线...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM