Рисование нескольких изображений на холсте с помощью image.onload - PullRequest
6 голосов
/ 15 июля 2010

У меня возникают проблемы при попытке нарисовать большой 2D-массив изображений на холсте. Используя отдельную программу, я беру один большой файл изображения и разбиваю его на более мелкие, однородные части. Я использую 2D-массив для представления этой «сетки» изображений, и в идеале, когда я назначаю src каждого элемента в сетке, это изображение будет нарисовано в нужной точке на холсте, как только будет готово. Однако мой код не работает.

var grid = new Array()  
/*grid is set to be a 2D array of 'totalRows' rows and 'totalCols' columns*/  

/*In the following code, pieceWidth and pieceHeight are the respective height/widths  
of each of the smaller 'pieces' of the main image. X and Y are the coordinates on  
the canvas that each image will be drawn at. All of the images are located in the  
same directory (The src's are set to http://localhost/etc), and each individual  
filename is in the form of name(row*totalRows + col).png, ex, traversing the 2D  
array left to right top to bottom would give image1.png, image2.png, etc*/  

for (var row = 0; row < totalRows; row++)  
    {  
        for (var col = 0; col < totalCols; col++)  
        {  
            grid[row][col] = new Image();  
            var x = col * pieceWidth;  
            var y = row * pieceHeight;  
            grid[row][col].onload = function () {ctx.drawImage(grid[row][col], x, y);};  
            grid[row][col].src = "oldimagename" +  ((row * totalRows) + col) + ".png";  
        }  
    }  

Я попытался запустить этот код в Opera, Firefox, Chrome и Safari. События загрузки не запускаются вообще в Opera, Chrome и Safari (я поместил предупреждение внутри функции загрузки, оно никогда не появлялось). В Firefox сработало только событие onload ПЕРВОГО изображения (grid [0] [0]). Тем не менее, я заметил, что, если я поместил предупреждение прямо ПОСЛЕ того, как я установил src текущего элемента, каждое событие загрузки в Firefox запускается, и все изображение рисуется. В идеале я хотел бы, чтобы это работало во всех 4 браузерах (я предполагаю, что IE не будет работать, потому что он не поддерживает Canvas), но я просто не знаю, что происходит. Любая помощь / вклад приветствуется, спасибо!

1 Ответ

10 голосов
/ 16 июля 2010

Я думаю, проблема в том, что вы не включаете переменные в замыкание. Измените эту строку:

grid[row][col].onload = function () {ctx.drawImage(grid[row][col], x, y);};

Для

grid[row][col].onload = function () {window.alert('row:' + row + ' col:' + col);};

И вы увидите , что ваши оповещения возвращают одно и то же значение для строки и столбца при каждом вызове. Вам необходимо заключить эти переменные в замыкание , чтобы ваша функция работала со значениями, а не со ссылками:

var drawCanvasImage = function(ctx,grid,row,col,x,y) {
    return function() {
        ctx.drawImage(grid[row][col], x, y);
    }
}

Затем выполните:

grid[row][col].onload = drawCanvasImage(ctx,grid,row,col,x,y);

Эта страница примера работает для меня в Firefox и Chrome.

...