Javascript Image.onload触发太快了

时间:2017-02-14 17:20:36

标签: javascript jquery html ajax

这看起来像是一个重复的问题,但我向你保证不会。

我从服务器端servlet提供的AJAX调用中加载了几个动态图像。我需要将图像分成三部分,但在图像加载之前我不能这样做。这让我想到了我的问题。我为每个图像都有一个onload触发器,但它在图像属性可用之前触发(例如高度,宽度等)。所以我的代码无法进行错误处理。

var imageData = [];

$( document ).ready(function() {
    preLoadImages();
});

function preLoadImages() {
    <c:forEach var="table" items="${tables}">
    var tmpImage = new imageObject(<c:out value="${table.tableRowId}" />);
    imageData.push(tmpImage);
    </c:forEach>

    for (var i = 0; i < imageData.length; i++) {
        ajaxGetmainImages(i);
    }
}

function imageObject(id) {
    this.id = id;
    this.mainImage = new Image();
    this.topImage = new Image();
    this.middleImage = new Image();
    this.bottomImage = new Image();
}

function split_3(i) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext("2d");

    if (imageData[i].mainImage.height > 2500) {
        $("#error_container-" + imageData[i].id).attr('display', "none");
        //document.getElementById('error_container').style.display = "none";

        var newWidth = imageData[i].mainImage.width;
        var newHeight = imageData[i].mainImage.height / 3;
        canvas.width = newWidth;
        canvas.height = newHeight;

        ctx.drawImage(imageData[i].mainImage, 0, 0, newWidth, newHeight, 0, 0, newWidth, newHeight);
        imageData[i].topImage.src = canvas.toDataURL();

        ctx.drawImage(imageData[i].mainImage, 0, (newHeight), newWidth, newHeight, 0, 0, newWidth, newHeight);
        imageData[i].middleImage.src = canvas.toDataURL();

        ctx.drawImage(imageData[i].mainImage, 0, ((newHeight * 2)), newWidth, newHeight, 0, 0, newWidth, newHeight);
        imageData[i].bottomImage.src = canvas.toDataURL();

        $("#left_image-" + imageData[i].id).attr('src', imageData[i].topImage.src);
        $("#right_image-" + imageData[i].id).attr('src', imageData[i].bottomImage.src);
    }
    else {
        $("#slider_container-" + imageData[i].id).attr('display', "none");
        $("#error_image-" + imageData[i].id).attr('src', imageData[i].mainImage.src);
    }

}

function ajaxGetmainImages(i)
{
    $.ajax({
        type: "GET",
        url: baseURL + '/admin/' + imageData[i].id,
        dataType: "json",
        async: true,
        success:function(data){
            imageData[i].mainImage.onload = split_3(i);
            imageData[i].mainImage.src = "data:image/jpg;base64," + data.image;
            //imageData[i].mainImage.addEventListener("load", split_3(i));
        },
        error:function(result){
            //$("#" + id + 'status').html("<img src='../resources/img/status-unknown-16.png' alt='Unknown'>");
        }
    });
}

图像ID是通过提供页面的servlet中的模型提供的。有了这个,我构建了唯一的URL来轮询每个图像。这段代码有效。我让它在一个单独的页面中运行,我只处理单个图像(图像被分割,以便可以使用滑块来比较图像)。但是,当我尝试使用多个图像时,在onload功能期间图像的高度始终为0。如果我在split_3函数中设置断点,我可以看到当处理 next 图像时,前一个图像现在具有非零高度值(正确的值)。

我尝试过Chrome Stable,Chrome Beta,Chrome Dev,Firefox和Opera,结果都是一样的。 onload似乎太早引发了一点,我不明白为什么。

编辑:一些额外的信息。图像最终加载。如果服务器端代码无法获取正确的图像,则它会提供默认占位符(因此else&gt;&#34; error_image&#34;)。但占位符不需要拆分。所以我在我的页面上得到的是错误占位符中的整个3倍高度图像。这是最终的问题。

2 个答案:

答案 0 :(得分:2)

addEventListener的参数必须是对函数的引用。您立即调用该函数并将结果传递给addEventListener。它应该是:

imageData[i].mainImage.addEventListener("load", function() {
    split_3(i));
});

onload

imageData[i].onload = function() { split_3(i); };

答案 1 :(得分:1)

感谢所有回复的人。我发现了这个问题。问题是我正在调用onload方法:

tableData[i].tableImage.onload = split_3(i);

立即调用它,因为它不是引用。我修改了以下代码。

tableData[i].tableImage.indexId = i;
tableData[i].tableImage.onload = split_3;
tableData[i].tableImage.src = "data:image/jpg;base64," + data.image;

我还将当前索引存储在图像对象本身中。这样我可以在触发onload时回调它。

function split_3() {
    var i = this.indexId;

其余代码无需任何更改即可运行。