在 iPad 上使用 JS 进行图像缓存
Image caching with JS on iPad
我正在开发一个用于iPad的纹理选择器。所以基本上只是一堆图像元素。为了避免图像重新加载和滞后,我在 JS 中缓存并重用Image
对象。有点像这个
/**
* Asynchronous version of memoize for use with callback functions. Asserts
* that last argument is the callback.
*
* @param {Function} func
* @return {Function}
*/
util.memoize.async = function(func) {
var cache = {};
return function() {
var hash = JSON.stringify(arguments);
var args = Array.prototype.splice.call(arguments, 0);
var callback = args.pop();
if (hash in cache) {
return callback.apply(this, cache[hash]);
}
args.push(function() {
cache[hash] = Array.prototype.splice.call(arguments, 0);
callback.apply(this, cache[hash]);
});
return func.apply(this, args);
};
};
/**
* Creates new Image element and calls back with loaded image.
* @param {string} url
*/
io.GetImage = function(url, callback) {
var img = new Image();
img.onload = function() {
callback(img);
};
img.src = url;
};
picker.image_ = util.memoize.async(io.GetImage);
然后,每当我需要图像时,我都会调用picker.image_
并获取缓存的图像。它在桌面,Chrome,Firefox,Safari上完美运行,但在iPad上,我得到了空的(未加载的)图像。为什么?我真的很喜欢这种方法,它的表现非常好。
看起来好像移动野生动物园从DOM中删除图像数据时会丢弃图像数据。可能是这样吗?
更新:澄清一下,正在加载的数据是动态的,因此它不是AppCache的最佳用例。
更新*:没有完全令人满意的答案,这是我的解决方案。请注意,复制方法非常慢。
/**
* Creates new Image element and calls back with loaded image.
* @param {string} url
*/
var GetImage = function(url, callback) {
var img = new Image();
img.onload = function() {
callback(img);
};
img.src = url;
};
/**
* @param {number} num maximum number of stored images
*/
var ImagePool = function(num) {
this.limit_ = num;
this.canvases_ = {};
this.order_ = [];
};
/**
* Retrieve image from cache.
*
* @param {string} url URL of request image
* @param {function(HTMLCanvasElement)} callback
*/
ImagePool.prototype.get = function(url, callback) {
if (this.canvases_[url] !== undefined) {
callback(this.copy_(url));
} else {
if (this.limit_ && this.order_.length == this.limit_) {
delete this.canvases_[url];
this.order_.pop();
}
GetImage(realUrl, function(img) {
var c = document.createElement('canvas');
c.width = img.width;
c.height = img.height;
var ctx = c.getContext('2d');
ctx.drawImage(img, 0, 0);
this.canvases_[url] = c;
this.order_.unshift(url);
callback(this.copy_(url));
}.bind(this));
}
};
/**
* @param {string} url
* @return {HTMLCanvasElement}
* @private
*/
ImagePool.prototype.copy_ = function(url) {
var c = document.createElement('canvas'),
cached = this.canvases_[url];
c.width = cached.width;
c.height = cached.height;
var ctx = c.getContext('2d');
ctx.drawImage(cached, 0, 0);
return c;
};
我认为您的问题可以通过使用 HTML 5 离线应用程序缓存来最好地解决。您列出要缓存的资源,并在用户访问请求这些资源的页面后,将缓存这些资源以供以后使用。您仍然需要让您的 UI 等待您的图像加载,但是一旦它们被加载,您就不必担心它们仅仅因为它们不在 DOM 中而被删除(这个 SO 问题表明在 DOM 中但未显示在屏幕上的图像也会被删除)。
显然,Safari Mobile有5MB的缓存限制,可以通过要求用户同意扩展它来增加(来源)。这篇博文中的评论表明,此扩展提示在iOS 4中可用。
有用的链接:
-
Apple Developer Guide for HTML 5 儲存 - 一些關於在 Safari 中使用 HTML 5 離線應用程式儲存的文稿。
-
概述类似性质的iPhone问题的博客文章 - 这是一篇较旧的博客文章(2009-2010),但作者对使用HTML 5功能有一些很好的建议(在"HTML5离线应用程序缓存"标题下)。
Image 对象直接附加到 DOM,则可能会在删除时丢失它,您可以在删除或附加之前尝试克隆它
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
您是否尝试过在服务器上设置适当的标头并让浏览器管理缓存而不是使用此方案?
我会使用嵌入式图像src base64编码。只需检查这里
因此,如果需要,您可以将数据存储为 JSON 的字符串,并在需要时取回它,如果您从其他 URL 调用图像,也可以将其保存到 localStorage。
是的,它给你带来了巨大的html内容和存储空间,但在你的情况下,这绝对值得。
- 如何缓存AJAX请求的图像
- 阻止浏览器缓存上载的图像
- ajax缓存false无法加载图像
- 从 PHP 脚本预缓存第二个图像
- 使用 javascript 时的图像缓存
- 使用脚本缓存图像
- 预加载图像和缓存图像之间有区别吗
- 上载图像的新版本并避免缓存
- 将图像保存到用户的pc缓存中,并使用asp.net从缓存中使用它
- 如何防止裁剪时浏览器图像缓存
- 如何在javascript中加载图像而不将其放入缓存中
- 图像加载,IE中的另一个错误 - 相当确定这不是缓存错误
- 在 iPad 上使用 JS 进行图像缓存
- 打破浏览器中的图像缓存
- 通过添加时间戳清除图像缓存
- 如何通过php脚本加载图像缓存
- 在高分辨率图像缓存后淡出
- 禁用图像缓存
- 我如何获得图像数据或在chrome或firefox网页上的图像缓存的路径
- 浏览器图像缓存和jQuery.load()问题