为什么不在HTML5 Canvas中绘制图像数组?

时间:2016-09-20 22:12:59

标签: javascript html5 canvas

我正在尝试使用画布绘制平铺地图。需要将三种类型的切片绘制到画布上,因此我不是为每个单独的图像调用函数三次,而是将图像数组作为参数传递,循环遍历数组,并告诉画布绘制每个图像。但是,当我这样做时,我得到一个空白画布,没有返回错误消息。当我没有传入数组但是为每个图像手动调用函数时,图像被绘制到画布上。谁能向我解释我做错了什么?

window.onload = function(){
    var basemap = document.getElementById("basemap");
    var basemapCtx = basemap.getContext("2d");
    initMap(Map.map, basemapCtx, basemap);
}

function initMap(map, ctx, canvas){
    var deepWater = new Image();
    var shallowWater = new Image();
    var coastalWater = new Image();
    deepWater.src = "deepWater.png";
    shallowWater.src = "shallowWater.jpg";
    coastalWater.src = "coastalWater.jpg";
    //Does not draw the images
    drawMap(map, [deepWater, shallowWater, coastalWater], ctx, canvas, [-2, -1, 0]);
    //Does draw the images
    //drawMap(map, deepWater, ctx, canvas, -2);
    //drawMap(map, shallowWater, ctx, canvas, -1);
    //drawMap(map, coastalWater, ctx, canvas, 0);
}

function drawMap(map, image, ctx, canvas, pos){
    var screenWidth = canvas.width;
    var screenHeight = canvas.height;
    var tileWidth = 0;
    var tileHeight = 0;
    var xPos = 0;
    var yPos = 0;
    for(var i = 0; i < image.length; i++){
        image[i].onload = function(){
            for(var rows = 0; rows < map.length; rows++){
                tileHeight = (screenHeight / map.length);
                for(var cols = 0; cols < map[rows].length; cols++){
                    tileWidth = (screenWidth / map[rows].length);
                    if(map[rows][cols] == pos[i]){
                        ctx.drawImage(image[i], xPos, yPos, tileWidth, tileHeight);
                    }
                    xPos += tileWidth;
                }
                xPos = 0;
                yPos += tileHeight;
            }
            yPos = 0;
            tileWidth = 0;
            tileHeight = 0;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在当前函数返回且Javascript什么都不做之前,onload事件才会触发。 for循环使用变量i。当onload事件触发时,i的值将是最后一个图像的image.length

您需要为每个onload事件创建对该调用唯一的变量。你可以使用闭包来做到这一点。

更改代码如下

function drawMap(map, image, ctx, canvas, pos){

    function setOnLoad(i){  // this function creates closure over the variable i so
                            // that it is unique each time this function and the onload
                            // function runs.
        var screenWidth = canvas.width;
        var screenHeight = canvas.height;
        var tileWidth = 0;
        var tileHeight = 0;
        var xPos = 0;
        var yPos = 0;
        // the following function closes over all the variables in this function
        image[i].onload = function(){
            for(var rows = 0; rows < map.length; rows++){
                tileHeight = (screenHeight / map.length);
                for(var cols = 0; cols < map[rows].length; cols++){
                    tileWidth = (screenWidth / map[rows].length);
                    if(map[rows][cols] == pos[i]){
                        ctx.drawImage(image[i], xPos, yPos, tileWidth, tileHeight);
                    }
                    xPos += tileWidth;
                }
                xPos = 0;
                yPos += tileHeight;
            }
        }
    }
    for(var i = 0; i < image.length; i++){
        setOnLoad(i);
    }
}

因此,每次调用onload函数时,您都将拥有一组唯一的变量。