我正在製作一個旨在用於iPad的紋理拾取器。所以基本上只是一堆圖像元素。爲了避免圖像重新加載和滯後,我緩存並重用JS中的Image
對象。排序這個在iPad上使用JS進行圖像緩存
/**
* 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上,我得到了空的(未加載的)圖像。這是爲什麼?我非常喜歡這種方法,它表現非常好。
它看起來就像移動Safari從DOM中刪除圖像數據時一樣。那可能嗎?
UPDATE:爲了說明,所加載的數據是動態的,因此它不是AppCache最適合的用例。
UPDATE *:還沒有完全令人滿意的答案,這是我的解決方案。請注意,複製方法非常慢。
/**
* 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;
};
那麼你爲什麼不把它放在DOM中並使其不可見? –
我必須竭盡全力在我的UI系統中做到這一點,絕對不是一個優雅的解決方案(我正在尋找)。 – skrat