0

私のキャンバス プロジェクトには、2 種類のスプライト オブジェクトがあります。ベクター グラフィックスで描画されるものと、キャンバスにビットマップ イメージが描画されるものです。

draw function(context){
 ...
 context.lineTo(some place)
 context.lineTo(some other place)
 etc.
}

もう 1 つのタイプのスプライトはビットマップ イメージです。現時点ではプレースホルダー アセットであるため、onload イベント ハンドラーを必要としないほど小さいですが、実際のアセットは大きくなるため、1 つ必要になります。

bitmap loadImage function(){

   this.image = new Image(); 
   //Currently my images are too small to warrant an onload eventHandler as they're placeholders
   this.image.src = "some path";
} 

現在、すべてのスプライトを同じコンテナーに格納し、単純なループで描画を実行しています。ビットマップスプライトにはオンロード機能がないため、これは今のところ機能します。

for each sprite {

 sprite.draw(context);
 }

プレースホルダー アセットをスプライト シートに置き換えたら、onload イベントに割り当てられた関数が必要になります。これは私の設計を妨げます。

すべてのスプライトを同じコンテナーに格納し、そのコレクションを反復処理してドローを呼び出す方法について、誰かが光を当てることができますか?

注: onload イベント ハンドラーを使用すると、ビットマップ描画が追加されますが、(明らかに) 画像が読み込まれる前にビットマップ スプライトで描画が呼び出されると、エラーが発生します。

4

2 に答える 2

2

すべての画像 URL を追加してから呼び出しload()てロードを開始できるようにするこのローダーを作成しました。

この種類のローダーを使用して進行状況のコールバックをサポートできるため、現在の進行状況をユーザーに表示できます。

クロスオリジン イメージが必要な場合は、イメージの crossOrigin タイプを設定するようにロード済みに指示するフラグを追加することで、これに対するサポートを追加できます。次の例では、すべての画像に対してこれを設定していますが、個々の画像に対してこれをサポートするように拡張できます。

ライブデモはこちら

ローダ:

/// callback - function to call when finished (mandatory)
/// progress - function to call for each image loaded (optional)
/// progress contains an argument with an "event" containing properties
/// img (the image loaded), url, current (integer) and total (integer)
function imageLoader(callback, progress, error) {

    if (typeof callback !== 'function') throw 'Need a function for callback!';

    var lst = [],
        crossOrigin = false;

    this.crossOrigin = function (state) {
        if (typeof state !== 'bool') return crossOrigin;
        crossOrigin = state;
        return this;
    }
    this.add = function (url) {
        lst.push(url);
        return this;
    }

    this.load = function () {
        if (lst.length > 0) {
            startLoading();
        }
        return this;
    }

    function startLoading() {

        var i = 0,
            url,
            count = lst.length,
            images = [];

        for (; url = lst[i]; i++) {
            var img = document.createElement('img');
            images.push(img);

            img.onload = function () {
                _handler(url, this)
            };
            img.onerror = function (e) {
                _handlerError(url, e)
            };

            if (crossOrigin === true) img.crossOrigin = 'anonymous';

            img.src = url;
        }

        function _handler(url, img) {

            count--;

            if (typeof progress === 'function') progress({
                current: lst.length - count,
                total: lst.length,
                url: url,
                img: img
            });

            if (count === 0) callback({
                images: images,
                urls: lst
            });
        }

        function _handlerError(url, e) {
            if (typeof error === 'function') error({
                url: url,
                error: e
            });

            console.warn('WARNING: Could not load image:', url);
            _handler();
        }
    }

    return this;
}

使用法:

var loader = new imageLoader(done, progress);

/// methods can be chained:
loader.add(url1)
      .add(url2)
      .add(url3)

      .load();

(完全な例についてはデモを参照)

その後、ハンドラーは次のことができます。

function done(e) {

    for (i = 0; i < e.images.length; i++) {

        /// draw the image
        ctx.drawImage(e.images[i], i * 20, i * 20, 40, 40);
    }
}

function progress(e) {

    ///progress bar
    status.style.width = ((e.current / e.total) * 100).toFixed(0) + '%';

    /// current loaded image
    ctx.drawImage(e.img, 0, 340, 60, 60);
}
于 2013-11-05T21:13:32.253 に答える