4

iPad で使用するためのテクスチャ ピッカーに取り組んでいます。つまり、基本的には画像要素の集まりです。画像のリロードと遅延を避けるためにImage、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 では空の (読み込まれていない) 画像が返されます。何故ですか?私はこのアプローチが本当に好きです。それは本当にうまく機能します。

Mobile Safari は、画像データが DOM から削除されると、画像データを削除するように見えます。それはありますか?

UPDATE : 明確にするために、ロードされるデータは動的であるため、AppCacheの最適な使用例ではありません。

更新* :完全に満足のいく答えはありませんでした。これが私の解決策です。copy メソッドは非常に遅いことに注意してください。

/**
 * 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;
};
4

4 に答える 4

5

あなたの問題は、HTML 5 オフライン アプリケーション キャッシュを使用することで最もよく解決できると思います。キャッシュしたいリソースをリストすると、ユーザーがそれらのリソースを要求するページにアクセスした後、後で使用できるようにキャッシュされます。画像が読み込まれるまでUIを待機させる必要がありますが、読み込まれると、DOMにないという理由だけでドロップされることを心配する必要はありません(このSOの質問は、画像がDOM にあるが、画面に表示されていないものもドロップされます)。

どうやら、Safari Mobile には 5MB のキャッシュ制限があり、ユーザーにキャッシュの拡張に同意するよう求めることで増やすことができます ( Source )。このブログ投稿のコメントは、この拡張プロンプトが iOS 4 で利用可能になることを示唆しています。

便利なリンク:

于 2012-06-22T15:45:30.550 に答える
3

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;
}
于 2012-06-26T17:21:16.070 に答える
2

このスキームを使用する代わりに、サーバーで適切なヘッダーを設定し、ブラウザーにキャッシュを管理させてみましたか?

于 2012-06-24T20:07:08.317 に答える
1

埋め込まれた画像srcbase64でエンコードされたものを使用します。ここをチェックしてください

したがって、必要に応じてデータを文字列としてJSONとして保存し、いつでも元に戻すことができます。別のURLから画像を呼び出す場合は、localStorageに保存することもできます。

そして、はい、それはあなたに巨大なhtmlコンテンツとストレージスペースを引き起こしますが、あなたの場合、それは間違いなくそれだけの価値があります。

于 2012-06-29T10:15:49.277 に答える