【发布时间】:2015-05-20 17:23:54
【问题描述】:
Contextxt:我目前正在开发一个使用 Angular 构建的 Web 应用程序,并使用 Silex 编写的 API。
我遇到以下情况:
- 一个 Angular 页面,包含多达数百个可点击的缩略图。点击后,灯箱插件会打开全尺寸图片
- 需要自定义令牌头来加载每张图片的 API
很好,我想,我创建了 API,所以它返回了 base64 编码的图像。很容易。将此 base64 编码数据设置为图像源更加简单:src = "data:image/jpeg;base64," + response;。这是使用ngSrc 完成的,使其有点异步。灯箱使用锚标签的href 来加载图像(我为此使用了 Colorbox),所以每张照片我有两个相当大的 base64-dataURL。
然而,这会导致严重的问题。不是立即只有一张图片,而是一旦图片数量开始增加。随着 base64-URL 保留在 DOM 中,浏览器选项卡开始需要越来越多的内存。
我为此创建了一个临时解决方法,方法是创建一个自定义 Silex 控制器,该控制器不从标头中读取其令牌,而是从查询字符串中读取。这使我可以将图像源设置为:src = "http://api/img/1?token=" + token;。数据 URL 及其内存不足的问题已经一去不复返了。
但是,在未来,API 很可能会开始要求 HTTP 基本身份验证来获取图像。并且基本身份验证凭据不能通过查询字符串传递。它们需要标头才能正常工作。所以我的解决方法将不再有效。因此,这是一个真正的临时解决方法。
我不完全确定如何解决这个问题。需要通过 Ajax 调用加载图像才能添加自定义标题。整个事情必须是异步的,因此加载速度尽可能快。加载图像后,无论显示多少图像,它都不应占用内存,或者至少不会占用太多内存以保持页面性能。
我一直在考虑将基于 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);
});
}
但我不确定这是否会并保持更高的性能。然而,我确信其他人以前必须处理过这样的情况。我忽略了什么吗?做一些完全错误的事情?我很想在这方面得到一些帮助,因为我目前被我不那么花哨的解决方法困住了......有人吗?
【问题讨论】:
标签: javascript canvas base64