У меня есть забавный маленький виджет, который предлагает пользователям выбирать из списка из 114 животных. Пользовательский интерфейс включает в себя маленькие эскизы каждого вида, все одинакового размера (100x70). Общая сумма миниатюр составляет 2,1 млн.
Я не собираюсь делать 114 запросов к серверу, поэтому я использовал ImageMagick, чтобы сделать одно ОЧЕНЬ длинное изображение (11400x70), которое уменьшается до 960К. Поэтому задача состоит в том, чтобы разделить это длинное изображение на 114 маленьких изображений на клиенте. ( РЕДАКТИРОВАТЬ: Мне нужно, чтобы каждое животное имело свое собственное изображение, потому что пользовательский интерфейс фильтрует список внизу, например, «показывать мне только травоядных»).
Первоначально у меня был сложный подход, когда я рисовал это большое изображение на холсте после загрузки строки base64 объединенного изображения, вытягивал ImageData для каждого животного, рисовал ТО на второй холст, а затем вытягивал dataURL:
var combined_canvas = document.createElement('canvas');
var combined_ctx = combined_canvas.getContext('2d');
var indv_canvas = document.createElement('canvas');
var indv_ctx = indv_canvas.getContext('2d');
combined_canvas.width = 11400; combined_canvas.height = 70;
indv_canvas.width = 100; indv_canvas.height = 70;
var image = new Image();
image.onload = function() {
combined_ctx.drawImage(image, 0, 0); // paint combined image
// loop through the list of 114 animals
Object.keys(master_list).forEach((d, i) => {
// get the image data just for this animal in sequence
var imageData = combined_ctx.getImageData(i * 100, 0, 100, 70);
// paint that image data to the second canvas
indv_ctx.putImageData(imageData, 0, 0);
var img = document.createElement('img');
img.src = indv_canvas.toDataURL();
document.getElementById("animal_thumbnails").appendChild(img);
});
};
image.src = combined_images; // the base64 of the combined image
Естественно, было бы НАМНОГО проще сделать 114 CSS Sprites , что также предотвратило бы небольшую потерю качества из-за того, как Canvas рисует изображения. Но я не очень хорошо понимаю, как браузеры хранят одно и то же изображение, размещенное много раз с разными смещениями.
В случае, если клиент дублирует объединенное изображение в памяти, я просматриваю около 100 МБ для всех этих миниатюр. Я надеюсь, что даже худший браузер умнее этого, но это слишком далеко, чтобы я не знал.
Причина, по которой я загружаю изображение как base64, заключается в том, что у меня была еще одна идея - декодировать base64 с помощью atob()
и нарезать его с помощью jpg-js , для этого Stackoverflow предложение . Но jpg-js добавляет около 300 КБ при минимизации, и я не уверен, что он когда-либо действительно предназначался для клиента.