简体   繁体   English

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

[英]How to cancel or abort image download in Three.js TextureLoader

I have an image gallery project where the user can move around the 3D space and the images start downloading as he gets near them. 我有一个图像库项目,用户可以在3D空间中移动图像,当他靠近图像时就开始下载图像。 Since he can be moving around all the time, getting away from those images which already started downloading, I'd need to cancel these downloads (they no longer need to download as they are not to be seen anymore). 由于他可以一直走动,远离已经开始下载的图像,因此我需要取消这些下载(不再需要下载,因为它们不再可见了)。

I download them with Three.TextureLoader and was hoping to find some method to stop/cancel/abort the download, but looks like it doesn't exist. 我使用Three.TextureLoader下载了它们,希望找到一些方法来停止/取消/中止下载,但看起来不存在。 I found these threads related to the topic: 我发现这些与主题相关的线程:

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

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

But I didn't find where to add the suggested "return request" in the Three code in my version of Three. 但是我没有在我的Three版本中的Three代码中在何处添加建议的“返回请求”。 I think this is the section where it should be found, but I don't quite get exactly where should I add such return statement: 我认为这是应该在其中找到的部分,但是我不太清楚应该在哪里添加这样的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
        }
    });

Can anybody point me in the right direction? 有人能指出我正确的方向吗? Or perhaps another solution such as loading the image in another way (jQuery, perhaps?) and then pass the texture to my material somehow? 还是另一种解决方案,例如以另一种方式加载图像(也许是jQuery?),然后以某种方式将纹理传递给我的材质? This is my current callback for TextureLaoder: 这是我当前对TextureLaoder的回调:

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

Many thanks 非常感谢

If you need to abort the image loader, check out the source code: https://github.com/mrdoob/three.js/blob/dev/src/loaders/ImageLoader.js 如果需要中止图像加载器,请查看源代码: https : //github.com/mrdoob/three.js/blob/dev/src/loaders/ImageLoader.js

The new ImageLoader().load(...) function returns an XHTML image element ( <img /> ). new ImageLoader().load(...)函数返回一个XHTML图像元素( <img /> )。 But this element is not accessible externally. 但是该元素不能从外部访问。 Therefore you can easily write your own function to load textures, and override the existing one. 因此,您可以轻松编写自己的函数来加载纹理,并覆盖现有的函数。

The function below is mostly copied from: https://github.com/mrdoob/three.js/blob/dev/src/loaders/TextureLoader.js Make sure that in the latest version of ThreeJS, you check if the source code below is the same (except for the additional abort function). 下面的函数主要从以下位置复制: 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;
};

Usage: 用法:

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);

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

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