Использование CSS-спрайтов: много раз репликация одного большого изображения обременяет клиента? - PullRequest
0 голосов
/ 09 января 2019

У меня есть забавный маленький виджет, который предлагает пользователям выбирать из списка из 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 КБ при минимизации, и я не уверен, что он когда-либо действительно предназначался для клиента.

1 Ответ

0 голосов
/ 09 января 2019

Что касается использования памяти, см. этот пост и этот пост

Таким образом, задача состоит в том, чтобы разделить это длинное изображение на 114 маленьких изображений. на клиенте.

Для чего нужно нарезать длинное изображение. Я хотел бы сохранить его как одно изображение и использовать как спрайт CSS и показывать все изображения.

Если ваши изображения имеют фиксированное измерение, цикл JavaScript может отображать все изображения на странице. Или вы можете использовать инструмент, подобный this , чтобы получить положение животного и сохранить его в файле CSS. Но я бы предпочел метод цикла JS.

Код будет выглядеть примерно так

var imageItem = "";
var x = 0;
for (var i = 0; i < 144, i++) {

  imageItem += "<li style='background-position: "+ x + " 0'></li>";
  x = x + 100; // this is the width of the each image
}

someElement.innerHtml = "<ul class='img-container'>" + imageItem + "</ul>";

В CSS

.img-container li {
  width: 100px;
  height: 70px;
  background-image : url('../your-long-image.jpg');
  background-repeat: no-repeat;
}

См. Этот пример, я использую только одно изображение, я изменяю положение смещения, чтобы показать разные местоположения на одном и том же изображении.

var imageItem = "";
var x = 0;
for (var i = 0; i < 3; i++) {
      
      imageItem += "<li style='background-position: "+ x + "px  0'>ss</li>";
      x = x - 125; // this is the width of the each image
}

    document.getElementById("container").innerHTML = "<ul class='img-container'>" + imageItem + "</ul>";
.img-container li {
      width: 125px;
      height: 200px;
      border: 1px solid green;
      background-image : url('https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/intermediary/f/c9702304-c06d-4500-90b7-b6b6168093f8/db9n9km-ee485eb1-1ecc-4cd8-b845-f16900bde9e0.png');
      background-repeat: no-repeat;
      float:left;
      list-style: none;
    }
<div id="container"></div>
...