使用 CSS Sprites:多次复制一张大图像是否会给客户造成负担?

Using CSS Sprites: Does replicating one large image many times burden the client?

我有一个有趣的小部件,它邀请用户从 114 种动物的列表中进行选择。 UI 包含每个物种的小缩略图,大小相同 (100x70)。缩略图总和为2.1M

我不急于发出 114 个服务器请求,所以我使用 ImageMagick 制作了一张非常长的图像 (11400x70),最终达到 960K。因此,挑战在于在客户端将长图像分割成 114 个小图像。 (编辑: 我需要每只动物作为自己的图像,因为 UI 过滤列表,例如 "show me only herbivores")。

我最初有一个复杂的方法,我在加载组合图像的 base64 字符串后将大图像绘制为 canvas,为每只动物提取 ImageData,将其绘制为第二个 canvas,然后拉取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 绘制图像的方式造成质量上的小损失。但我不太了解的是 浏览器如何存储多次放置不同偏移量的相同图像。

如果客户端在内存中复制组合图像,我正在寻找大约 100Mb 的所有这些缩略图。我希望即使是最糟糕的浏览器也能比这更智能,但这对我来说太深奥了。

我将图像加载为 base64 的原因是我的另一个想法是用 atob() 解码 base64,然后用 jpg-js, per this Whosebug suggestion 将其切碎。但是 jpg-js 在缩小时增加了大约 300K,我不确定它是否真的适用于客户端。

关于内存使用,请看this post and this post

So the challenge is to chop up that long image into 114 small images on the client.

长图需要剁什么。我会将其保留为单个图像并用作 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>