如何在Three.js TextureLoader中取消或中止图像下载

时间:2018-07-08 15:06:17

标签: javascript three.js

我有一个图像库项目,用户可以在3D空间中移动图像,并且当他靠近它们时就开始下载图像。由于他可以一直走动,远离已经开始下载的图像,因此我需要取消这些下载(不再需要下载,因为它们不再可见了)。

我使用Three.TextureLoader下载了它们,希望找到一些方法来停止/取消/中止下载,但似乎不存在。我发现这些线程与该主题有关:

https://github.com/mrdoob/three.js/pull/6649

https://github.com/mrdoob/three.js/issues/6641

但是,在我的Three版本中,我找不到在Three代码中添加建议的“返回请求”的位置。我认为这是应该在其中找到的部分,但是我不太清楚应该在哪里添加这样的return语句:

Object.assign(Ja.prototype, {
        load: function(a, b, c, d) {
            void 0 === a && (a = "");
            void 0 !== this.path && (a = this.path + a);
            a = this.manager.resolveURL(a);
            var e = this
              , f = jd.get(a);
            if (void 0 !== f)
                return e.manager.itemStart(a),
                setTimeout(function() {
                    b && b(f);
                    e.manager.itemEnd(a)
                }, 0),
                f;
            if (void 0 !== Ta[a])
                Ta[a].push({
                    onLoad: b,
                    onProgress: c,
                    onError: d
                });
            else {
                var g = a.match(/^data:(.*?)(;base64)?,(.*)$/);
                if (g) {
                    c = g[1];
                    var h = !!g[2]
                      , g = g[3]
                      , g = window.decodeURIComponent(g);
                    h && (g = window.atob(g));
                    try {
                        var k = (this.responseType || "").toLowerCase();
                        switch (k) {
                        case "arraybuffer":
                        case "blob":
                            for (var l = new Uint8Array(g.length), h = 0; h < g.length; h++)
                                l[h] = g.charCodeAt(h);
                            var m = "blob" === k ? new Blob([l.buffer],{
                                type: c
                            }) : l.buffer;
                            break;
                        case "document":
                            m = (new DOMParser).parseFromString(g, c);
                            break;
                        case "json":
                            m = JSON.parse(g);
                            break;
                        default:
                            m = g
                        }
                        window.setTimeout(function() {
                            b && b(m);
                            e.manager.itemEnd(a)
                        }, 0)
                    } catch (t) {
                        window.setTimeout(function() {
                            d && d(t);
                            e.manager.itemEnd(a);
                            e.manager.itemError(a)
                        }, 0)
                    }
                } else {
                    Ta[a] = [];
                    Ta[a].push({
                        onLoad: b,
                        onProgress: c,
                        onError: d
                    });
                    var n = new XMLHttpRequest;
                    n.open("GET", a, !0);
                    n.addEventListener("load", function(b) {
                        var c = b.target.response;
                        jd.add(a, c);
                        var d = Ta[a];
                        delete Ta[a];
                        if (200 === this.status) {
                            for (var f = 0, g = d.length; f < g; f++) {
                                var h = d[f];
                                if (h.onLoad)
                                    h.onLoad(c)
                            }
                            e.manager.itemEnd(a)
                        } else if (0 === this.status) {
                            console.warn("THREE.FileLoader: HTTP Status 0 received.");
                            f = 0;
                            for (g = d.length; f < g; f++)
                                if (h = d[f],
                                h.onLoad)
                                    h.onLoad(c);
                            e.manager.itemEnd(a)
                        } else {
                            f = 0;
                            for (g = d.length; f < g; f++)
                                if (h = d[f],
                                h.onError)
                                    h.onError(b);
                            e.manager.itemEnd(a);
                            e.manager.itemError(a)
                        }
                    }, !1);
                    n.addEventListener("progress", function(b) {
                        for (var c = Ta[a], d = 0, e = c.length; d < e; d++) {
                            var f = c[d];
                            if (f.onProgress)
                                f.onProgress(b)
                        }
                    }, !1);
                    n.addEventListener("error", function(b) {
                        var c = Ta[a];
                        delete Ta[a];
                        for (var d = 0, f = c.length; d < f; d++) {
                            var g = c[d];
                            if (g.onError)
                                g.onError(b)
                        }
                        e.manager.itemEnd(a);
                        e.manager.itemError(a)
                    }, !1);
                    void 0 !== this.responseType && (n.responseType = this.responseType);
                    void 0 !== this.withCredentials && (n.withCredentials = this.withCredentials);
                    n.overrideMimeType && n.overrideMimeType(void 0 !== this.mimeType ? this.mimeType : "text/plain");
                    for (h in this.requestHeader)
                        n.setRequestHeader(h, this.requestHeader[h]);
                    n.send(null)
                }
                e.manager.itemStart(a);
                return n
            }
            return n
        },
        setPath: function(a) {
            this.path = a;
            return this
        },
        setResponseType: function(a) {
            this.responseType = a;
            return this
        },
        setWithCredentials: function(a) {
            this.withCredentials = a;
            return this
        },
        setMimeType: function(a) {
            this.mimeType = a;
            return this
        },
        setRequestHeader: function(a) {
            this.requestHeader = a;
            return this
        }
    });

有人能指出我正确的方向吗?还是另一种解决方案,例如以另一种方式加载图像(也许是jQuery?),然后以某种方式将纹理传递给我的材质?这是我当前对TextureLaoder的回调:

   obj.handleTexture = function (size, texture) {
        obj.mesh.material.map = texture;
        obj.mesh.material.needsUpdate = true;  
    };

非常感谢

1 个答案:

答案 0 :(得分:0)

如果需要中止图像加载器,请查看源代码:https://github.com/mrdoob/three.js/blob/dev/src/loaders/ImageLoader.js

new ImageLoader().load(...)函数返回一个XHTML图像元素(<img />)。但是该元素不能从外部访问。因此,您可以轻松编写自己的函数来加载纹理,并覆盖现有的函数。

下面的函数主要从以下地方复制:https://github.com/mrdoob/three.js/blob/dev/src/loaders/TextureLoader.js确保在最新版本的ThreeJS中,您检查下面的源代码是否相同(除了附加的中止功能之外)。

THREE.TextureLoader.prototype.load = function(url, onLoad, onProgress, onError)
{
    var texture = new THREE.Texture();
    var loader = new THREE.ImageLoader(this.manager);
    loader.setCrossOrigin(this.crossOrigin);
    loader.setPath(this.path);
    var image = loader.load(url, function(image)
    {
        texture.image = image;
        // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
        var isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
        texture.format = isJPEG ? THREE.RGBFormat : THREE.RGBAFormat;
        texture.needsUpdate = true;
        if(onLoad !== undefined)
        {
            onLoad( texture );
        }
    }, onProgress, onError);

    // add this function to the texture
    texture.abort = function()
    {
        if(image && typeof image.hasAttribute === 'function')
        {
            image.src = '';
        }
    };
    return texture;
};

用法:

var texLoader = new THREE.TextureLoader();
var texRequest = texLoader.load('https://example.com/image.jpg', function(texture)
{
    clearTimeout(texTimer);
    // use loaded texture
    ...
});

// For example, abort after 200ms if still loading:
var texTimer = setTimeout(function()
{
    texRequest.abort();
}, 200);