简体   繁体   中英

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. 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. I found these threads related to the topic:

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

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. 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:

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? This is my current callback for 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

The new ImageLoader().load(...) function returns an XHTML image element ( <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).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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