Javascript:在没有 base64-dataURL 的情况下从自定义 API 将许多图像加载到 DOM
Javascript: Loading many images into DOM from a custom API without base64-dataURLs
Contextxt:我目前正在使用 Angular 和用 Silex 编写的 API 构建 web-app。
我遇到了以下情况:
- Angular-page 有多达数百个可点击的缩略图。单击时,lightbox-plugin 打开 full-size 图像
- API 需要自定义 token-header 来加载每张图片
很好,我想,我做了 API 所以它返回了 base64 编码的图像。很容易。将这个 base64 编码的数据设置为图像源更简单:src = "data:image/jpeg;base64," + response;
。这是使用 ngSrc
完成的,使其有点异步。灯箱使用 anchor-tag 的 href
从中加载图像(为此我使用 Colorbox),因此每张照片我有两个相当大的 base64-dataURL。
然而,这会导致严重的问题。不是立即只有一张图片,而是图片数量开始增加时。浏览器选项卡开始需要越来越多的内存,因为 base64-URL 保留在 DOM.
中
我为此创建了一个临时解决方法,方法是创建一个自定义 Silex 控制器,该控制器不从 headers 而是从 query-string 读取其令牌。这允许我将图像源设置为:src = "http://api/img/1?token=" + token;
。 data-URLs 的问题和他们的记忆饥饿问题已经一去不复返了。
但是,将来 API 很可能会开始要求 HTTP 基本身份验证来获取图像。并且基本身份验证凭据不能通过查询字符串传递。它们需要 headers 才能运行。所以我的解决方法将不再有效。因此,这是一个真正的临时解决方法。
虽然我不完全确定如何解决这个问题。需要通过 Ajax-call 加载图像才能添加自定义 headers。整个事情必须是异步的,所以加载尽可能快。加载图像后,它不应占用内存,或者至少不会占用太多内存以保持页面性能,无论显示多少图像。
我一直在研究将基于 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);
});
}
但是我不确定这是否会并且保持更高的性能。然而,我确信其他人以前必须处理过这样的情况。我忽略了什么吗?做错了什么?我很想就此获得一些帮助,因为我目前仍坚持使用 not-so-fancy 解决方法...有人吗?
Canvas 使用与 img 元素一样多的内存来显示图像,因此使用 canvas 不会帮助您解决内存问题。
自从您累积编码 urls 来存储图像数据以来,您就会遇到不断增加的内存需求。
考虑到您当前灯箱的局限性,"rolling your own" 可能会给您带来更好的效果。
如何只为您的初始显示提供缩略图,然后将单个全尺寸 img 元素的 .src
属性 更改为所选缩略图的 url。
这样一来,您只需为缩略图显示和一张全尺寸图像占用内存。让浏览器缓存全尺寸图像,这样如果您的用户重新查看以前的全尺寸图像,它将快速从缓存中获取而不是重新下载。
Contextxt:我目前正在使用 Angular 和用 Silex 编写的 API 构建 web-app。
我遇到了以下情况:
- Angular-page 有多达数百个可点击的缩略图。单击时,lightbox-plugin 打开 full-size 图像
- API 需要自定义 token-header 来加载每张图片
很好,我想,我做了 API 所以它返回了 base64 编码的图像。很容易。将这个 base64 编码的数据设置为图像源更简单:src = "data:image/jpeg;base64," + response;
。这是使用 ngSrc
完成的,使其有点异步。灯箱使用 anchor-tag 的 href
从中加载图像(为此我使用 Colorbox),因此每张照片我有两个相当大的 base64-dataURL。
然而,这会导致严重的问题。不是立即只有一张图片,而是图片数量开始增加时。浏览器选项卡开始需要越来越多的内存,因为 base64-URL 保留在 DOM.
中我为此创建了一个临时解决方法,方法是创建一个自定义 Silex 控制器,该控制器不从 headers 而是从 query-string 读取其令牌。这允许我将图像源设置为:src = "http://api/img/1?token=" + token;
。 data-URLs 的问题和他们的记忆饥饿问题已经一去不复返了。
但是,将来 API 很可能会开始要求 HTTP 基本身份验证来获取图像。并且基本身份验证凭据不能通过查询字符串传递。它们需要 headers 才能运行。所以我的解决方法将不再有效。因此,这是一个真正的临时解决方法。
虽然我不完全确定如何解决这个问题。需要通过 Ajax-call 加载图像才能添加自定义 headers。整个事情必须是异步的,所以加载尽可能快。加载图像后,它不应占用内存,或者至少不会占用太多内存以保持页面性能,无论显示多少图像。
我一直在研究将基于 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);
});
}
但是我不确定这是否会并且保持更高的性能。然而,我确信其他人以前必须处理过这样的情况。我忽略了什么吗?做错了什么?我很想就此获得一些帮助,因为我目前仍坚持使用 not-so-fancy 解决方法...有人吗?
Canvas 使用与 img 元素一样多的内存来显示图像,因此使用 canvas 不会帮助您解决内存问题。
自从您累积编码 urls 来存储图像数据以来,您就会遇到不断增加的内存需求。
考虑到您当前灯箱的局限性,"rolling your own" 可能会给您带来更好的效果。
如何只为您的初始显示提供缩略图,然后将单个全尺寸 img 元素的 .src
属性 更改为所选缩略图的 url。
这样一来,您只需为缩略图显示和一张全尺寸图像占用内存。让浏览器缓存全尺寸图像,这样如果您的用户重新查看以前的全尺寸图像,它将快速从缓存中获取而不是重新下载。