2017-04-11 71 views
0

Three.js(R84)的当前版本使用图像标签来加载纹理,该纹理不支持onProgress事件。我可以推断加载了多少文件,但无法公开关于加载的字节的详细信息。使用XHR进度事件在Three.js中加载纹理

用onProgress事件支持加载纹理的最佳方法是什么?我想支持多种移动客户端,但传统桌面支持不是问题。

+0

看看[这](http://blogs.adobe.com/webplatform/2012/01/13/html5-image-progress-events/) – 2pha

回答

2

一个解决方案是先通过FileLoader加载文件,然后使用TextureLoader从缓存中加载。内存中缓存意味着文件只加载一次,即使它没有从服务器获取缓存头。

结果是我们通过FileLoader的初始AJAX获取获取进度事件,但仍可以利用适当TextureLoader的所有有用行为(例如禁用JPEG纹理的alpha通道以及其他优化)。

/** 
* Loads THREE Textures with progress events 
* @augments THREE.TextureLoader 
*/ 
function AjaxTextureLoader() { 
    /** 
    * Three's texture loader doesn't support onProgress events, because it uses image tags under the hood. 
    * 
    * A relatively simple workaround is to AJAX the file into the cache with a FileLoader, create an image from the Blob, 
    * then extract that into a texture with a separate TextureLoader call. 
    * 
    * The cache is in memory, so this will work even if the server doesn't return a cache-control header. 
    */ 

    const cache = THREE.Cache; 

    // Turn on shared caching for FileLoader, ImageLoader and TextureLoader 
    cache.enabled = true; 

    const textureLoader = new THREE.TextureLoader(); 
    const fileLoader = new THREE.FileLoader(); 
    fileLoader.setResponseType('blob'); 

    function load(url, onLoad, onProgress, onError) { 
     fileLoader.load(url, cacheImage, onProgress, onError); 

     /** 
     * The cache is currently storing a Blob, but we need to cast it to an Image 
     * or else it won't work as a texture. TextureLoader won't do this automatically. 
     */ 
     function cacheImage(blob) { 
      // ObjectURLs should be released as soon as is safe, to free memory 
      const objUrl = URL.createObjectURL(blob); 
      const image = document.createElementNS('http://www.w3.org/1999/xhtml', 'img'); 

      image.onload =()=> { 
       cache.add(url, image); 
       URL.revokeObjectURL(objUrl); 
       document.body.removeChild(image); 
       loadImageAsTexture(); 
      }; 

      image.src = objUrl; 
      image.style.visibility = 'hidden'; 
      document.body.appendChild(image); 
     } 

     function loadImageAsTexture() { 
      textureLoader.load(url, onLoad,()=> {}, onError); 
     } 
    } 

    return Object.assign({}, textureLoader, {load}); 
} 

module.exports = AjaxTextureLoader; 
+1

非常甜蜜的解决方案! – pailhead