4

次のような機能を実行する関数を使用して、いくつかの画像を描画します。

context.drawImage(img, width / 2 * (-1), height / 2 * (-1), width, height);

次のようなもので、画像を描画する前に画像が読み込まれるのを待つ必要があることを読みました。

img.onload = function() {
    context.drawImage(img, width / 2 * (-1), height / 2 * (-1), width, height);
};

ただし、これにより画像が描画されますが、単純なゲームの「アニメーション」ループの一部であるため、数ミリ秒ごとに描画関数を呼び出すため、その後は何も描画されません。

init() 関数でコードを実行し続ける前に、onload イベントを待つ方法はありますか?

次のようなものだと思います:

var image_loaded = false;
img.onload = function() {
    image_loaded = true;
};
if(image_loaded) {
    animate();
}

動作する必要がありますか?image_loaded が true になるまで init() を呼び出し続けるために timeOut 関数を追加する必要がない限り?

4

2 に答える 2

4

ライブデモ

var imagesLoaded = [],
    images = [
        'http://www.zombiegames.net/inc/screenshots/The-Last-Stand-Union-City.png', 
    'http://www.zombiegames.net/inc/screenshots/Lab-of-the-Dead.png',
    'http://www.zombiegames.net/inc/screenshots/Zombotron.png',
    'http://www.zombiegames.net/inc/screenshots/Road-of-the-Dead.png'],
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d");

canvas.width = 640;
canvas.height = 480;

function init(){
    // just loops through the images.
    if(imagesLoaded.length > 0){
        ctx.drawImage(imagesLoaded[0], 0, 0, 640, 480);
        imagesLoaded.push(imagesLoaded.shift());   
    }
    setTimeout(init,500);
}

function preload(){
    for(var i = 0; i < images.length; i++){
        (function(value){
            return function(){
                var loadedImage = new Image();
                loadedImage.src = images[value];
                loadedImage.onload = function(){
                    imagesLoaded.push(loadedImage);  
                } 
            }();
        })(i);

    }
    checkLoaded();
}

function checkLoaded(){
    if(imagesLoaded.length === images.length){
        console.log(imagesLoaded.length);
        init(); 
    } else{
        setTimeout(checkLoaded,30);
    }
}

preload();

上記は、画像をプリロードして他の処理を待機する方法の例です。基本的に、すべての画像を配列にonload入れて、それぞれにイベントを追加します。それらが読み込まれると、読み込まれたすべての画像を保持する別の配列に読み込まれます。2 つの配列の長さが一致したら、すべての画像を使用する準備が整います。

別の方法は、読み込み時にカウンターをインクリメントし、その値を配列の長さと照合することです。カウンター変数が画像配列の長さと等しい場合、それらはすべて読み込まれ、使用する準備ができていることを意味します。

于 2013-05-15T13:32:07.773 に答える
3

画像の読み込みを簡単にするために、シンプルで小さなライブラリを作成しました。

デモを確認する

以下のライブラリ コードを参照してください。

// Simple Image Loader Library
window.Loader = (function () {
var imageCount = 0;
var loading = false;
var total = 0;

// this object will hold all image references
var images = {};

// user defined callback, called each time an image is loaded (if it is not defined the empty function wil be called)
function onProgressUpdate() {};
// user defined callback, called when all images are loaded (if it is not defined the empty function wil be called)
function onComplete() {};

function onLoadImage(name) {        
    ++imageCount;
    console.log(name + " loaded");

    // call the user defined callback when an image is loaded
    onProgressUpdate();

    // check if all images are loaded
    if (imageCount == total) {
        loading = false;
        console.log("Load complete.");
        onComplete();
    }

};

function onImageError(e) {
    console.log("Error on loading the image: " + e.srcElement);
}

function loadImage(name, src) {
    try {
        images[name] = new Image();
        images[name].onload = function () {
            onLoadImage(name);
        };
        images[name].onerror = onImageError;
        images[name].src = src;
    } catch (e) {
        console.log(e.message);
    }
}

function getImage(/**String*/ name){
    if(images[name]){
        return (images[name]);
   }
    else{
        return undefined; 
    }
}

// pre-load all the images and call the onComplete callback when all images are loaded
// optionaly set the onProgressUpdate callback to be called each time an image is loaded (useful for loading screens) 
function preload( /**Array*/ _images, /**Callback*/ _onComplete, /**Callback <optional>*/ _onProgressUpdate) {
    if (!loading) {

        console.log("Loading...");
        loading = true;

        try {
            total = _images.length;
            onProgressUpdate = _onProgressUpdate || (function(){});
            onComplete = _onComplete || (function(){});                

            for (var i = 0; i < _images.length; ++i) {
                loadImage(_images[i].name, _images[i].src);                    
            }
        } catch (e) {
            console.log(e.message);
        }
    } else {
        throw new Error("Acess denied: Cannot call the load function while there are remaining images to load.");
    }
}

// percentage of progress
function getProgress() {
    return (imageCount / total)*100;
};

// return only the public stuff to create our Loader object
return {
    preload: preload,
    getProgress: getProgress,
    getImage: getImage,
    images: images // have access to the array of images might be useful but is not necessary
};
})();

使い方

画像がロードされ、アプリケーションで使用できることを確認するために、ライブラリにはLoader.preloadメソッドがあります。

preload メソッドはオブジェクトの配列を受け取ります。各オブジェクトには、ロードするイメージの名前と src プロパティが含まれています。必要に応じて、onCompleteコールバック (すべての画像が読み込まれるときに呼び出される) とonProgressUpdateコールバック (画像が読み込まれるたびに呼び出される) を設定できます。コールバックは、onProgressUpdateアプリケーションの読み込み画面を作成する場合に役立ちます。

を使用しLoader.getProgress()て、いつでもロードされたイメージのパーセンテージを取得します。

Loader.getImage(name)読み込まれた画像の参照を取得するには、 name が画像の name プロパティ (文字列) である を呼び出します。

何らかの理由ですべての画像を反復処理する必要がある場合は、 を使用しますLoader.images。プロパティに画像のすべての参照を含むオブジェクトです。

次のように使用します。

var images = [{name: "img1", src: "http://...a.."}, 
              {name: "img2", src: "http://...b.."},
              ...
              {name: "imgN", src: "http://...N.."}];

function onProgressUpdate(progress){
    ...
    drawProgressBar(progress); // just an example of what you can do
    ...
}

function onComplete(){
    ...        
    // get an Image from Loader object
    var texture = Loader.getImage("img2");
    // or use this:
    var texture = Loader.images.img2; // or still Loader.images["img2"]
    ...

    // iterate over the images
    for (var img in Loader.images){
        console.log(Loader.images[img].src);
    }
    ....
}

Loader.preload(images, onComplete, onProgressUpdate);

そうでない場合は、デモを確認してください。

于 2013-05-15T19:19:59.597 に答える