【发布时间】:2019-01-09 23:19:47
【问题描述】:
我有一个有趣的小部件,它邀请用户从 114 种动物的列表中进行选择。 UI 包括每个物种的小缩略图,大小相同 (100x70)。缩略图总和为 2.1M。
我并不急于发出 114 个服务器请求,所以我使用 ImageMagick 制作了一张非常长的图像 (11400x70),它缩小到 960K。因此,挑战是在客户端将那个长图像分割成 114 个小图像。 (编辑:我需要每个动物都作为自己的图像,因为 UI 会过滤列表,例如“只显示食草动物”)。
我最初有一个复杂的方法,我在加载组合图像的 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 绘制图像的方式造成质量上的小幅损失。但我不太了解的是浏览器如何存储相同的图像,多次放置不同的偏移量。
如果客户端在内存中复制组合图像,我会为所有这些缩略图查看大约 100Mb。我希望即使是最糟糕的浏览器也比这更智能,但这对于我来说太遥远了。
我将图像加载为 base64 的原因是我的另一个想法是使用 atob() 解码 base64 并使用 jpg-js 将其分割,每个 this Stackoverflow suggestion。但是 jpg-js 在缩小后增加了大约 300K,我不确定它是否真的是为客户设计的。
【问题讨论】:
-
你不会制作 114 个 CSS 精灵。 CSS sprite 正是您所做的,将许多图像组合在一起。现在你要做的就是把这张图片设置为div的背景,div为70x70px,然后移动背景来显示你想要的图片。 div 就像一个窗口。
-
对,但我需要每只动物作为自己的过滤节点(例如,只显示食肉动物),所以我需要 114 个 div,对吧?
-
您的问题似乎与浏览器有关。您是在询问一组特定的浏览器,还是常见的浏览器实现?
-
后者——主要是在一个页面上多次放置同一张图片的约定。
标签: javascript css image canvas css-sprites