单击JSFiddle中的Run后,代码突然出现。什么?

时间:2014-02-10 23:39:53

标签: javascript firefox canvas

我制作了一个jsFiddle,用于演示JavaScript中的像素操作。它在Chrome中运行得非常好。然后我开始在Firefox上测试它。

它不起作用,它引发了一个错误:

  

IndexSizeError: Index or size is negative or greater than the allowed amount

这让我很困惑。但是等等,还有更多。

当我再次点击Run时,代码突然有效。我不知道这是什么巫术,或者只是一些奇怪的Firefox bug。

您可以在此处查看问题:http://jsfiddle.net/DerekL/RdK7H/
当您在jsFiddle中时,单击选择文件并选择一个PNG文件。你应该看到代码不起作用。然后单击“运行”。再做同样的事情,它突然起作用。

Firefox中的一些功能也存在一些问题,这也让我感到沮丧,但这并不是这个问题的一部分。

如果你需要知道,我使用的是Firefox 26.0。

1 个答案:

答案 0 :(得分:1)

这是因为您的图像尚未完成加载,因此返回图像的默认宽度和高度(均为0)。由于您无法使用0作为getImageData()的宽度和高度,因此会出现错误。

  

当我再次单击“运行”时,代码突然运行。我不知道是什么   巫术就是这个,或者它只是一些奇怪的Firefox bug。

这是因为图像现在位于缓存中,并且在您尝试读取其宽度和高度之前,浏览器恰好能够提供它(不,错误在您的代码中:-) )。

使用busy循环和超时值处理图像加载是乞求失败。

确保向图像添加onload处理程序(这可能需要您稍微重构代码以支持回调(或承诺),并且返回值将无效,原因与错误):

getRGBArray: function(uri, callback){  /// add parameter for callback here
    var image = new Image();

    image.onload = imageLoaded;        /// add an onload handler here

    image.src = uri;

    function imageLoaded() {
        //var t = Date.now();
        //while(Date.now() - t < 3000 && !image.width);

        var width = this.width,   /// replace image with this to be sure you
            height = this.height, /// ..are dealing with the correct image in
            canvas = $("<canvas>").attr({ /// ..case you load several ones..
                width: width,
                height: height
            }).appendTo("body"),
            ctx = canvas[0].getContext("2d");

        ctx.drawImage(this, 0, 0);
        var imgData = ctx.getImageData(0, 0, width, height).data;

        ...

        callback(imgData);  /// example of callback
    }
...
}

可选择分开图像加载,这样您就可以调用此功能,而不必依赖图像是否已加载。

<强>更新

如前所述,您可以将图像加载与主代码分开。例如 - 不是在getRGBArray()函数中加载图像,而是将其预先加载到代码中的其他位置并将图像作为参数传递(回调无法避免,但您可以在加载后保持原始代码同步点):

function loadImage(url, callback) {

    var image = new Image();
    image.onload = function() {
        callback(this);
    }
    image.src = uri;
}

然后像这样调用它:

loadImage(url, readyToGo);

function readyToGo(image) {

    var pixels = getRGBArray(image);
    ...
}

原始函数中的一个小修改,使其使用传递的图像而不是url:

getRGBArray: function(image){

    var width = image.width,
        height = image.height,
        canvas = $("<canvas>").attr({
                width: width,
                height: height
            }).appendTo("body"),
            ctx = canvas[0].getContext("2d");

        ctx.drawImage(image, 0, 0);
        var imgData = ctx.getImageData(0, 0, width, height).data;

        ...

        return opt;
    }
...
}

希望这有帮助!