AS3: Как получить URL-адрес динамического загрузчика из LoaderInfo в функции "Слушатель событий"?

Я загружаю много изображений, и использую массив для этого.

loader[i].load(new URLRequest(picture[i]));

Функция "Слушатель событий моего события" активирована следующим образом:

loader[i].contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);   

Мой обработчик событий onComplete показывает это:

trace(e.target); //OUTPUT: [object LoaderInfo]

Я искал свойства в LoaderInfo, которые могли бы определить, какой загрузчик инициировал прослушиватель (значение "i" ), чтобы я мог указать каждый из них конкретно:

bitmapDataArr[i] = e.target.content.bitmapData;
bmVisArr[i] = new Bitmap(bitmapDataArr[i]);

Но не может определить, какой "i" инициировал конкретный экземпляр слушателя.

Любые идеи? Я попытался дать имя LoaderInfo безрезультатно. Я все еще не могу извлечь искомый маленький идентификационный номер.

EDIT показывает цикл для загрузчиков и функцию onComplete:

for (i = 0; i < 10; i++) {
    loader[i] = new Loader();
    loader[i].contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete, false, 0, true);           
    loader[i].load(new URLRequest(letter[i]));
}

private function onComplete(e:Event):void {
    trace("e.target",e.target); //OUTPUT: e.target    [object LoaderInfo]
    var LI:LoaderInfo = e.target as LoaderInfo;
    var eNum:int = (????);
    bitmapDataArr[eNum] = e.target.content.bitmapData;
    bmVisArr[eNum] = new Bitmap(bitmapDataArr[eNum]);
}

Ответ 1

Вам нужно как-то принести значение i в функцию onComplete. Например, в контексте this или через аргумент.

P.S.: Легче использовать слабый реф. Словари вместо удаления свойств, хотя я мало что знаю о AS3.

Вот пример, который также показывает, как удалить прослушиватели событий (включая их функции обратного вызова):

/* An object containing callback
 * functions used along with event listeners.
 */
const callbacks: Object = {};


/* This function will re-declare and hoist i
 * in itself. */
private function loop(i: uint): void {
    loader[i] = new Loader;

    const wrapped =
    callbacks[i] = function wrapper(...args) {
        // Pass all arguments (respectively event and i)
        onComplete.apply(null, args);

        // Function#apply(thisContext, arguments)
        // Rest exp. isn't implemented yet, else we could just do:
        // onComplete(...args);
    };

    loader[i].contentLoaderInfo
        .addEventListener(Event.COMPLETE, wrapped, false,
            0, true);

    loader[i].load(new URLRequest(letter[i]));
};

for (var i: uint = 0; i < 10; ++i) loop(i);

private function onComplete(e: Event, i: uint): void {
    const loaderInfo: LoaderInfo = e.target as LoaderInfo;

    bitmapDataArr[i] = e.target
        .content.bitmapData;

    bmVisArr[i] = new Bitmap(bitmapDataArr[i]);

    loader[i].contentLoaderInfo
        .removeEventListener(
            Event.COMPLETE, callbacks[i]
        );

    // Deletes the property that stores
    // the function inside callbacks
    delete callbacks[i];
}

Ответ 2

После публикации этого вопроса я использовал следующий класс. Он принимает целое число (количество изображений для загрузки) и дает открытый доступ к массиву спрайтов в массиве "ShapeArr".

Каждое свойство имени спрайта выводится из его имени URL. (имя: "pic1" из загруженного url "assets/pic1.png" )

У меня возникли проблемы со всей концепцией/реализацией встроенных функций и вместо этого использовал этот подход.

package {
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Sprite;
import flash.events.Event;

public class MultipleImageLoader extends Sprite {
    {private var pic:Array = [
        "assets/pic1.png",  "assets/pic2.png",  "assets/pic3.png",  "assets/pic4.png",
    ]}

    private var loader:Array = [];

    public var ShapeArr:Array = [];
    public var bitmapDataArr:Array = [];
    public var bmVisArr:Array = [];     
    private var shapeText:Array = [];       
    private var picArray:Array = [];

    private var count:int = 0;
    private var loaderCounter:int = 0;
    private var numPicsToLoad:int;
    private var a:String;
    public var loaded:Boolean = false;

    public function MultipleImageLoader(numPics:int):void {
        numPicsToLoad = numPics;
        loaded = false;

        init();
    }

    private function init(e:Event = null):void {
        if (hasEventListener(Event.ADDED_TO_STAGE)) {
            removeEventListener(Event.ADDED_TO_STAGE, init);
        }
        picArray = new Array;
        for (var i:int = 0; i < numPicsToLoad; i++) {
            picArray.push(i);
        }
        initiateLoaders();
    }

    private function initiateLoaders():void{
        loader[loaderCounter] = new Loader;
        loader[loaderCounter].contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete, false, 0, true);

        a = pic[picArray[loaderCounter]];
        //trace("shapecolor load:", a);
        shapeText[loaderCounter] = (a.substr(16, a.length - 20));
        loader[loaderCounter].load(new URLRequest(a ) );
    }

    private function onComplete(e:Event):void {
        //trace("sssssssssssssssssssssssssshapecolor");
        bitmapDataArr[loaderCounter] = e.target.content.bitmapData;
        bmVisArr[loaderCounter] = new Bitmap(bitmapDataArr[loaderCounter]);
        bmVisArr[loaderCounter].scaleX = .1;
        bmVisArr[loaderCounter].scaleY = .1;
        bmVisArr[loaderCounter].x =-bmVisArr[loaderCounter].width / 2;
        bmVisArr[loaderCounter].y =-bmVisArr[loaderCounter].height / 2;

        ShapeArr[loaderCounter] = new Sprite();
        ShapeArr[loaderCounter].name = a.substr(7,4);

        trace("Name",loaderCounter,ShapeArr[loaderCounter].name );

        ShapeArr[loaderCounter].addChild(bmVisArr[loaderCounter]);
        loader[loaderCounter].contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
        if (loaderCounter <numPicsToLoad-1) {
            loaderCounter += 1;
            initiateLoaders();
        }
        //trace("gonna count",count);
        counting();
        count += 1;
    }

    private function counting():void {
        trace("tile count", count,numPicsToLoad);
        if (count < numPicsToLoad-1) {
            return;
        }
        else{
            removeEventListener(Event.ENTER_FRAME, counting);
            loaded = true;
            count = 0;
            trace("All Images LOADED");
        }
    }   
}//end  Class
}//end Package