Contextxxt:我目前正在开发一个使用 Angular 构建的 Web 应用程序,并使用 Silex 编写的 API。
我遇到以下情况:
- 带有多达数百个可点击缩略图的 Angular 页面。单击时,灯箱插件会打开全尺寸图像
- 需要自定义 token header 来加载每张图片的 API
很好,我想,我创建了 API,以便它返回 base64 编码的图像。很容易。将此 Base64 编码数据设置为图像源更加简单:src = "data:image/jpeg;base64,"+ response;
。这是使用 ngSrc 完成的,使其有点异步。灯箱使用 anchor 标记的 href
来加载图像(我使用 Colorbox 来实现),因此每张照片我有两个相当大的 base64-dataURL。
但这会导致严重的问题。不是只有一张图片时立即,而是当图片数量开始增加时。由于 base64-URL 保留在 DOM 中,浏览器选项卡开始需要越来越多的内存。
我通过创建一个自定义 Silex Controller 为此创建了一个临时解决方法,该 Controller 不从 header 而是从查询字符串读取其 token 。这允许我将图像源设置为:src = "http://api/img/1?token="+ token;
。数据 URL 及其内存消耗的问题已经消失。
但是,将来 API 很可能会开始要求 HTTP 基本身份验证来获取图像。并且基本身份验证凭据无法通过查询字符串传递。它们需要 header 才能发挥作用。所以我的解决方法将不再有效。因此,这是一个真正的临时解决方法。
但我不完全确定如何解决这个问题。需要通过 Ajax 调用加载图像才能添加自定义 header 。整个过程必须是异步的,因此加载速度尽可能快。加载图像后,它不应占用内存,或者至少不会占用太多内存,以保持页面性能,无论显示多少图像。
我一直在考虑将基于 base64 的图像加载到 canvas
元素上。像这样的事情:
$scope.loadThumbnails = function() {
$scope.photos.forEach(function($photo){
$photo.canvas_th = document.querySelector('canvas#' + $photo.id + '_th');
var request = $http({
method: "GET",
url: [URL]
});
var fetchThumbnailSuccess = function(response) {
console.debug("Fetched thumbnail with id " + $photo.id);
// Get drawing context
var ctx = $photo.canvas_th.getContext("2d");
// Create image with onload drawing to context
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
// Add data to image object, triggering the onload function which in turn draws the image to the context
img.src = 'data:image/jpeg;base64,' + response;
}
request.success(fetchThumbnailSuccess);
var fetchThumbnailFailure = function(response) {
console.error("Failed fetching thumbnail with id " + $photo.id);
console.debug(response);
}
request.error(fetchThumbnailFailure);
});
}
但是我不确定这是否会并且保持更高的性能。但我确信其他人以前一定也处理过这样的情况。我是否忽略了什么?做一些完全错误的事情吗?我很想获得一些帮助,因为我目前陷入了不太花哨的解决方法......有人吗?
最佳答案
Canvas 使用与 img 元素一样多的内存来显示图像,因此使用 canvas 将无法解决内存问题。
只要您不断积累编码的网址来存储图像数据,您就会一直面临不断增加的内存需求。
鉴于您当前的灯箱的局限性,也许“滚动您自己的灯箱”会给您带来更好的性能。
如何为您的初始显示提供缩略图,然后将单个全尺寸 img 元素的 .src
属性更改为所选缩略图的 URL。
这样,您只占用缩略图显示和单个全尺寸图像的内存。让浏览器缓存全尺寸图像,这样,如果您的用户重新查看以前的全尺寸图像,它将快速从缓存中获取,而不是重新下载。
关于Javascript:从自定义 API 将许多图像加载到 DOM 中,无需使用 base64-dataURLs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30356417/