Ситуация
У меня есть сетчатый неупорядоченный список с 144 (90px x 90px) изображениями (12x12), которые могут быть повернуты. Моя конечная цель - взять сетку изображений 144 и сохранить ее как 1 изображение.
Текущее решение
Мое текущее решение позволяет мне выполнить следующие действия:
- Создайте холст с шириной изображения шириной x 12 и высотой изображения x 12. Это означает изображение конечного продукта.
- Прокрутите список элементов (изображений), извлекая изображение src из элемента и нарисуйте его на своем собственном холсте, который является размером изображения.
- Поворот нового маленького холста, однако изображение было повернуто на сетке.
- Нарисуйте новый маленький холст на холсте конечного результата в x и y текущего указателя.
Заметки
Когда я просматриваю изображения, я отслеживаю указатель (где я сейчас на холсте). Я делаю это, поддерживая строку и номер столбца. Они представляют текущую строку и столбец изображений, которые я рисую. Я использую их, умноженные на ширину и высоту одного изображения, чтобы получить точные координаты x и y на холсте, чтобы нарисовать следующее изображение.
Текущая проблема
Когда я вызываю функцию для создания, рисования и генерации base64 холста, я получаю следующее сообщение об ошибке: "InvalidStateError: была сделана попытка использовать объект, который не является или больше не может использоваться"., Если эта ошибка возникла в 100% случаев, я бы предположил ее, потому что изображение, которое я рисую на холсте, либо еще не загружено, либо вообще не загружается, но я получаю эту ошибку только один раз за каждое новое изображение загружается. Например, если у меня есть сетка изображений 144, это два разных изображения, каждый из которых нарисован 72 раза, я получу InvalidStateError дважды, а затем в третий раз, когда я вызову функцию, это будет успешным.
Текущий код
Пожалуйста, имейте в виду, что это просто код спайка для проверки сохранения изображения, я знаю, что требуется рефакторинг.
generateThumbnail: function(){
var builder = this,
canvas = document.createElement('canvas'),
content,
row = 0,
col = 0;
// width is single image width (90) x number of tiles wide (usually 12)
canvas.width = 90 * builder.grid[0];
// height is single image height (90) x number of tiles high (usually 12)
canvas.height = 90 * builder.grid[1];
// get 2d context of new canvas
context = canvas.getContext("2d");
// loop through all of the images on the grid
$.each($(".pattern-grid li"), function(i, tile) {
var $tile = $(tile),
image = new Image(),
src = $tile.find("img").attr("src"),
width,
height,
buffer,
bufferctx,
x,
y;
// set crossOrigin of image to anonymous as these images are loaded via CORS
image.crossOrigin = "Anonymous";
// increase row number by 1 if it has reached the end of the row and its not the first image being drawn
if(i % builder.grid[0] == 0 && i != 0){
row++;
}
// Set Column to 0 if it is a new row, otherwise increase column by 1 (unless it is the first image being drawn)
if(col == builder.grid[0]-1){
col = 0;
}else if(i != 0){
col++;
}
// determine if there was no image drawn at this location
if(src != undefined){
image.src = src;
// get the width and height the image, to be used for the small canvas and where to draw it
width = image.width;
height = image.height;
// create a new buffer canvas to draw the image to, this will be used to apply any rotations that may exist
buffer = document.createElement("canvas");
//set width and height of the buffer to the current images width and height
buffer.width = width;
buffer.height = height;
bufferctx = buffer.getContext("2d");
//Determine x and y coordinates to draw the small canvas using row and column numbers
x = col*width;
y = row*height;
//Save current state of buffer canvas
bufferctx.save();
//translate and then rotate the buffer canvas by the image rotation
bufferctx.translate(width/2, height/2);
bufferctx.rotate($tile.find("img").data("rotation")*Math.PI/180);
bufferctx.translate(width/2*-1, height/2*-1);
//draw image to buffer canvas and restore its context
bufferctx.drawImage(image, 0, 0);
bufferctx.restore();
//draw the buffer canvas to the main canvas at predetermined x and y
context.drawImage(buffer, x, y, width, height);
}
});
return canvas.toDataURL();
}