JavaScript:从字节数组创建图像资源

javascript: create an image resource from a byte array

本文关键字:创建 图像 资源 数组 字节数 字节 JavaScript      更新时间:2023-09-26

我有一个网页,里面充满了javascript,还有一些对资源(如图像)的引用,供javascript使用。我使用 websocket 与服务器通信;JavaScript 解析套接字的数据,并相应地对页面表示执行操作。一切都很好,除非它不工作。

问题似乎是该页面包含我想在javascript控制下显示部分图像的图像。无论我如何使用 defer,显然在某些情况下,在 javascript 尝试使用它们之前,图像似乎没有完全下载。结果是呈现页面时图像丢失,在很小比例的情况下。

我不太习惯语言和协议,在这些语言和协议中,

您无法严格控制何时发生的事情,因此服务器和浏览器以不受控制和异步的顺序发送内容和执行内容让我很恼火。所以我想停止依赖像推迟这样明显不可靠的技巧。我想做的是下载整个页面,然后打开我的 websocket 并通过它发送我的图像和其他资源。当该过程完成后,我将知道接受来自 websocket 的其他命令并继续执行页面操作是安全的。换句话说,我想颠覆浏览器对资源的异步处理,并在javascript控制下串行处理它们。

将图像文件从服务器倒入套接字很容易,而且我可以毫不费力地提出协议来做到这一点。将数据捕获为字节数组也很容易。

但是,如何将它们解释为图像呢?

我知道这种方法有缺点。我不会得到我的图像的浏览器缓存,初始页面不会加载得那么快。我没意见。我只是厌倦了 95% 的工作解决方案,不得不怀疑我所做的是否适用于每个可以想象的浏览器。(从IE 8到明年的Chrome的所有工作对我来说都是一个要求。

这种方法可行吗?有没有更好的方法来获得严格、便携的资源加载控制?

除了图像之外,您仍然没有非常具体地说明您正在等待哪些资源,但如果它们都是图像,那么您可以使用此loadMonitor对象来监视 N 个图像何时完成加载:

function loadMonitor(/* img1, img2, img3 */) {
    var cntr = 0, doneFn, self = this;
    function checkDone() {
        if (cntr === 0 && doneFn) {
            // clear out doneFn so nothing that is done in the doneFn callback
            // accidentally cause the callback to get called again
            var f = doneFn;
            doneFn = null;
            f.call(self);
        }
    }
    function handleEvents(obj, eventList) {
        var events = eventList.split(" "), i;
        function handler() {
            --cntr;
            for (i = 0; i < events.length; i++) {
                obj.removeEventListener(events[i], handler);
            }
            checkDone();
        }
        for (i = 0; i < events.length; i++) {
            obj.addEventListener(events[i], handler);
        }
    }
    this.add = function(/* img1, img2, img3 */) {
        if (doneFn) {
            throw new Error("Can't call loadMonitor.add() after calling loadMonitor.start(fn)");
        }
        var img;
        for (var i = 0; i < arguments.length; i++) {
            img = arguments[i];
            if (!img.src || !img.complete) {
                ++cntr;
                handleEvents(img, "load error abort");
            }
        }
    };
    this.start = function(fn) {
        if (!fn) {
            throw new Error("must pass completion function as loadMonitor.start(fn)");
        }
        doneFn = fn;
        checkDone();
    };
    // process constructor arguments
    this.add.apply(this, arguments);
}
// example usage code
var cardsImage = new Image();
cardsImage.src = ...
var playerImage = new Image();
playerImage.src = ...
var tableImage = new Image();
var watcher = new loadMonitor(cardsImage, playerImage, tableImage);
// .start() tells the monitor that all images are now in the monitor
// and passes it our callback so it can now tell us when things are done
watcher.start(function() {
    // put code here that wants to run when all the images are loaded
});
// the .src value can be set before or after the image has been 
// added to the loadMonitor
tableImage.src = ...

请注意,您必须确保您放入 loadMonitor 中的所有图像都分配了.src,否则 loadMonitor 将永远不会调用其回调,因为该图像永远不会完成。

工作演示:http://jsfiddle.net/jfriend00/g9x74d2j/