在HTML5画布上绘制多个图像有时候不起作用

3
我正在尝试在画布(canvas)中绘制多个图像。当我加载页面时,代码能够正常工作(每个图像都在正确的位置绘制),但是当我重新加载页面时,只有一个图像会被绘制(在正确的位置)。
代码简单地使用for循环遍历一组图像URL,并确定该图像应位于何处。
当我重新加载页面并且只有一个图像被绘制时,这个图像恰好是页面头部的图像。如果我转到另一个运行相同代码但具有不同页眉图像的页面,它将正确显示所有图像,但是当我重新加载页面时,只有也恰好位于页眉中的图像会被正确显示。如果我回到第一个页面,则所有图像都会正确显示,如果我重新加载,则只有也恰好位于页眉中的图像会显示。
// Get the image
var image = new Image();
var image_load = function( img, x_pos, y_pos, width, height ) {

    // Draw the image
    context.drawImage( img, x_pos, y_pos, width, height );
};
image.src = image_url[index];
image.onload = image_load( image, x_position, y_position, img_size, img_size );

我已确保图像URL都已正确设置,位置和大小也正确。另一件我注意到的事情是,当我通过代码打破image对象时,outerHTMLsrc属性总是被正确设置,但只有当图像正确显示时,currentSrc才会被设置,而在没有正确显示图像时,它被设置为""
我已经花了几个小时来试验这个问题,但所有我找到的在线示例都没有起作用。如有任何帮助,将不胜感激。
1个回答

2
似乎您正在执行image_load函数,而不是将其分配给load事件侦听器。在事件发生时,您应该传递一个要执行的函数处理程序,在您的情况下,您正在传递image_load结果,根据您的代码示例,这是undefined
请尝试使用以下代码行替换您的代码:
image.onload = function(){ image_load( image, x_position, y_position, img_size, img_size ); };

请注意,我们传递了一个函数,当执行该函数时,将使用所需的参数调用image_load,而不是立即执行它。 编辑: 如果您在所有处理程序中使用相同的变量,则需要考虑图片加载需要时间,在此期间,您可能会用新的图像细节覆盖先前定义的参数,可能导致所有图像接收来自最后一次调用的值,这些值定义了这些变量。在这种情况下,我建议有两个解决方案。
  1. Wrap your code so that every image will defined its own variables.

    function createImage(image_url, x_position, y_position, width, height) {
        var image = new Image();
        image.onload = function() {
            var context;
            // ... Some code ...
            // Draw the image
            context.drawImage( image, x_position, y_position, width, height );
        };
        image.src = image_url;
        return image;
    }
    
请注意,我们通过父函数createImage传递参数,该函数创建了一个新的作用域。每个函数执行都将有自己独立的作用域,值不会混合在一起。
  1. You can bind the values to the event handler this way.

    var image = new Image();
    var image_load = function( img, x_pos, y_pos, width, height ) {
    
        // Draw the image
        context.drawImage( img, x_pos, y_pos, width, height );
    };
    image.src = image_url[index];
    image.onload = image_load.bind( null, image, x_position, y_position, img_size, img_size );
    

Bind将返回一个函数的版本,该函数会自动将其上下文设置为null(函数内的this将为null),并将前几个参数设置为:image、x_position、y_position、img_size、img_size。由于我们将值绑定到函数中,即使变量的值发生变化,也不会影响我们的处理程序。

如果由我决定,我可能会将这两个函数分开,像这样:

function loadImage(x_position, y_position, width, height) {
    var context;
    // ... Some code ...
    // Draw the image
    context.drawImage(this, x_position, y_position, width, height);
}

function createImage(image_url, x_position, y_position, width, height) {
    var image = new Image();
    image.onload = loadImage.bind(image, x_position, y_position, width, height);
    image.src = image_url;
    return image;
}

使用loadImage图像作为上下文(this)。

附言: 我在image.onloadimage.src = ...之间切换,最好在设置源并开始图像下载之前设置事件处理程序


那样就有意义并且运行……差不多吧。我现在遇到的问题是每个“image_load”函数都使用最后一张图片的图像、x_position等值被执行。所以,如果我应该在10个不同的位置上获取10个不同的图像,现在我有了10个相同位置上的相同图像。 - B1NARY
可能是因为您每次都在覆盖相同的变量。请给我一分钟,我会编辑我的答案来解决这个问题。 - iMoses
太棒了!非常感谢,它完美地运行。 - B1NARY
1
很好的回答,感谢指出我的错误。我已经删除了。 - Rick Hitchcock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接