AS3 loading image from Array into empty movieclip - actionscript-3

I have tried this to load image path from database via php and load the image in flash. Now how can i add child to every single image to a every single empty movie clip for the farther use. the code is
var ldr:URLLoader = new URLLoader(new URLRequest("m_shirts.php"));
ldr.addEventListener(Event.COMPLETE, _done);
function _done(e:Event):void {
ldr.removeEventListener(Event.COMPLETE, _done);
var ar:Array = String(e.target.data).split("#");
for (var x:int=0; x<ar.length; x++){
/*var img:Loader = new Loader();
img.load(new URLRequest(ar[x]));
shirts.addChild(img);*/
var myLoader:Loader = new Loader();
var my_mc:MovieClip = new MovieClip();
myLoader.load(new URLRequest(ar[x]));
my_mc.addChild(myLoader);
addChild(my_mc);
my_mc.x= my_mc.width + 50;
}
}

Ok, I will try to answer this from what I understand:
You simply cannot convert Loader instances to a MovieClip. A Loader is a Loader and a MovieClip is a MovieClip, much like an Array is an Array or a Function is a Function. Their common base class is DisplayObjectContainer. It has most of the functionality MovieClips have except for child manipulation (although the methods are there) and drawing API as per the graphics property.
You can access the size of the loaded image by reading the Loader's width and height.
Your problem seems to be, that you want to determine the image's size before it is loaded. You cannot do that. You have to wait for it to load first. The contentLoaderInfo will dispatch an Event.COMPLETE when the image is available.

Related

For loops, arrays and movie clips - how to achieve a dynamic system

I am working on a Flash scene that reads from an XML file to "build" up an animation itself.
Reading the XML is no problem, that works like a charm. My issue is when I come to placing the assets (images) on to the stage.
My code is below:
import flash.display.Sprite;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.MovieClip;
var xmlLoader:URLLoader;
var builderXml:XML;
var container:MovieClip = new MovieClip();
var assetsArray:Array = new Array();
var bg:Sprite;
stage.addChild(container);
init();
function init():void
{
xmlLoader = new URLLoader();
xmlLoader.load(new URLRequest("build_me.xml"));
xmlLoader.addEventListener(Event.COMPLETE, processXML);
}
function processXML(e:Event):void {
builderXml = new XML(e.target.data);
for (var i:int = 0; i < builderXml.assets.*.length(); i++){
var image:MovieClip = new MovieClip();
var assetArray:Array = new Array();
image.x = builderXml.assets.asset[i].start.position.x;
image.y = builderXml.assets.asset[i].start.position.y;
trace(image.x);
assetArray.push(builderXml.assets.asset[i].source);
assetArray.push(builderXml.assets.asset[i].start.scale);
assetArray.push(builderXml.assets.asset[i].start.position.x);
assetArray.push(builderXml.assets.asset[i].start.position.y);
assetArray.push(builderXml.assets.asset[i].start.rotation);
assetArray.push(image);
assetsArray.push(assetArray);
var lc:LoaderContext = new LoaderContext();
lc.checkPolicyFile = false;
var loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
var _myURLRequest = new URLRequest(builderXml.assets.asset[i].source);
loader.load(_myURLRequest, lc);
function onImageLoaded(e:Event):void
{
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onImageLoaded);
image.addChild(e.target.content);
}
container.addChild(assetsArray[i][5]);
}
trace(assetsArray);
}
My XML has 2 assets listed, one 1280 x 720 image for a backdrop and the other is a simple logo that I want to position, using set x and y coordinates.
The problem is that both assets are being added to the same movieclip, despite the fact I am creating a new MC instance inside the FOR loop.
How can I get the assets to adhere to separate movieclips that I can then store in the array (pretty sure I am storing the current MC properly in the array, just happens that the MC contains 2 images, not 1 a piece)
Also, why is it that I cannot access the variable "i" inside the "onImageLoaded" function? It sits inside the FOR loop...
You are using a global variable inside a listener, and expect it to not being changed when the listener would actually fire. Listeners are asynchronous, so you should track which of the loaders fired a Event.COMPLETE event so that you could retrieve a correct instance of image MC out of those prepared at the XML parsing step, and only then stuff the loader's content inside it. This my answer has a method of doing just that, the method you should use is similar to the one that's used to retrieve a corresponding progress bar over there.

Loading google maps static images into flash

I'm trying to load images from google maps static images api into flash. When I attempt to load them flash complain about sandbox issues. Even after I try and load the policy file from google.
Security.loadPolicyFile("http://maps.googleapis.com/crossdomain.xml");
Is there any way around this? or is it simply impossible to load images in this fashion?
var loader1:Loader = new Loader();
var lctx1:LoaderContext = new LoaderContext(true);
loader1.contentLoaderInfo.addEventListener(Event.INIT, doImgInit);
loader1.load(new URLRequest("http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=14&size=600x400&maptype=satellite&sensor=false&scale=4"), lctx1);
private function doImgInit(evt:Event):void
{
trace("DO IT")
// get a reference to the LoaderInfo object in which the image is loaded
var lInfo:LoaderInfo = evt.target as LoaderInfo;
// this variable is used as reference to the image in the end.
var dO:DisplayObject;
// try to access the "content" property of the loader, if it works, there is a crossdomain.xml file.
try{
dO = lInfo.loader.content;
}
// if there wasn't one, we need to put the loader inside another object in order to manipulate it
catch(err:SecurityError)
{
// create a new Sprite to contain the loaded image
var sprt:Sprite = new Sprite();
// add the loader to the sprite
sprt.addChild(lInfo.loader);
// get a reference to this sprite in the dO variable
var dO:DisplayObject = sprt as DisplayObject;
}
// from here on you can do anything to the dO variable, rotate it, draw it unto a bitmapData, move it around..
// but first don't forget to add to to some container that is on the stage so you can see it!
}

How to convert loaded SWF to bitmapdata?

I use the loader class to load some png files to the stage. The function that is called after the file is loaded is something similar to this:
private function IconLoaded(e:Event):void
{
percentLoaded_txt.visible = false;
iconLoader = Loader(e.target.loader);
icone = Bitmap(iconLoader.content);
icone.smoothing = true;
var _icon: imgBox;
_icon = new imgBox(_MAX_WIDTH, _MAX_HEIGHT, icone,0);// new imgHelper(_bitmap);
_icon.x = _main.cena.width/2;
_icon.y = _main.cena.height/2;
addChild(_icon);
}
imgBox is a class that auto resize the bitmap and allow also to add border for example...
My code works fine, to load PNG files. But I want also to be able to load swf files.
How can I do this?
Thanks.
You will need to make a copy of the loaded SWF into a Bitmap.
function copyIt(obj:DisplayObject):Bitmap {
var bd:BitmapData = new BitmapData( obj.width, obj.height );
bd.draw(obj);
return new Bitmap(bd);
}
var bmpCopy:Bitmap = copyIt(mySWF);
addChild(bmpCopy);
You can't load a swf as a bitmap data because they are totally distinct types. What you can do is load a swf and add it as a child of a movie clip to show its content.
This link shows how to load a swf. After loading it, you just need to add this as a child of a MovieClip and add this movieclip to the stage to show its content.

How do I prevent a Loader from changing my apps position and size?

I load an SWF using a simple loader but it changes the main applications x/y position and size.
Which loader do I use to load an swf that will maintain the position size of my app?
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, function handleInit(event:Event):void{
var UIDesigner:UIComponent = new UIComponent();
UIDesigner.addChild(event.target.loader.content);
UIDesigner.id = "id_sample";
ApplicationObject.Instance.addElementAt(UIDesigner,0)
event.target.content.addEventListener(FlexEvent.APPLICATION_COMPLETE, function applicationCompleteHandler(event:Event):void{
var app:SystemManager = event.target as SystemManager;
var Designer:SkinnableContainer = app.application as SkinnableContainer;
Designer.id = "id_test";
ApplicationObject.Instance.removeElementAt(0);
pTabCon.addChild(Designer as SkinnableContainer);
pTabCon.horizontalScrollPolicy = "off";
pTabCon.verticalScrollPolicy = "off";
Parent.id_ComponentsTab.addChild(pTabCon);
Parent.id_ComponentsTab.selectedChild = pTabCon;
trace("swf loaded successfully");
ApplicationObject.Instance.m_ApplicationList.addItem(Designer);
});
});
The problem is not the Loader but how you use it and specifically, how you add the content to the stage.
A DisplayObjectContainer will change size according to its content. For instance , if you load a MovieClip with a width of 400 in another MovieClip with a 200 width, the containing MovieClip width will change to 400. This is an expected behavior.
It's possible to modify this behavior by using masking for instance or modifying the loaded content properties before adding content to the stage.
As for the x & y properties, it would have to do with your code. Loading content shouldn't change the x & y properties of the containing Object.
If you edit your question and add some code example we may be able to give you more specific help.
does the swf that you load call root or maybe stage? i've had such issue with an swf animated background for my app.
and how do load it?
upd: you can always use NO_SCALE
loadSWFFile("resources/awords/myswf.swf");
private function loadSWFFile(fileURL:String):void
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleSWFLoadComplete0);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler0);
loader.load( new URLRequest(fileURL));
}
private function handleSWFLoadComplete0( evt:Event ):void
{
loaderWidth = evt.currentTarget.loader.width;
loaderHeight = evt.currentTarget.loader.height;
// Now set the width and height of target component same as loaderWidth and loaderHeight respectively.
}
private function ioErrorHandler0(e:IOErrorEvent):void
{
mx.controls.Alert.show("Unable to load", "IOError", 0);
}

How Do I Reference a Dynamically Instantiated Object in AS3? (Added a Moviclip to the Stage)

This is something that has been bugging me since I took up AS3 a year ago.
Example. I make a class that extends a Movie Clip and call it "LoaderBar" all it is is some text that says "Loading" and below it another movie clip that is a plain rectangle that I call "lBar"
When I call a function to load my image I add the Loader to the stage as such..
function imageLoader(URL:String):void
{
var loader:Loader = new Loader(new URLRequest(URL));
loader.contentLoaderInfo.addEventListner(ProgressEvent.PROGRESS, progressHandler);
var loadBar:Loader Bar = new LoaderBar();
addChild(loadBar);
}
function progressHandler(e:Event):void
{
var pcent:Number = e.getBytesLoaded / e.getBytesTotal;
// HERE IS WHERE I'D LIKE TO MAKE DIRECT REFERENCE TO MY LOADBAR;
loadBar.lBar.width = pcent*100;
}
Essentially I just want to tell the lBar in the loadBar Movie Clip to be the width of the percent *100. (so that when the clip is loaded the loader bar is 100 pixels wide).
My problem is this. When I add the loadBar to the stage inside of a function, I cannot make reference to it inside of another function without doing some hack making a global variable outside of my function like...
var loadBarClip:MovieClip;
and inside the load function assigning the loadBar to the loadBarclip as such
loadBarClip = loadBar.
I feel like this is redundant. Does anyone know of anyway of accessing my loadBar without making a reference variable?
If it's just for that handler, you could make the handler anonymous and keep in inside the current scope.
var loadBar = new LoaderBar();
var loader:Loader = new Loader(new URLRequest(URL));
loader.contentLoaderInfo.addEventListner(
ProgressEvent.PROGRESS, function (e:Event):void {
var pcent:Number = e.getBytesLoaded / e.getBytesTotal;
loadBar.lBar.width = pcent*100; //Here you are making a direct reference.
}
);
If you really want to encapsulate your scopes you could use closures:
returnFromEncapulatingClosure = function(){
var loadBar = new LoaderBar();
var loader:Loader = new Loader(new URLRequest(URL));
return {
loadBar: loadBar,
loader: loader
};
}();
That allows you to bundle together some references so they won't clobber other parts of code, and you could refer to it with:
returnFromEncapulatingClosure.loader.contentLoaderInfo.addEventListner(ProgressEvent.PROGRESS, progressHandler);
function progressHandler(e:Event):void {
var pcent:Number = e.getBytesLoaded / e.getBytesTotal;
returnFromEncapulatingClosure.loadBar.lBar.width = pcent*100;
}
As a footnote, when you extend the Movie Clip, add a method that sets the lBar.width. Something like:
loadbar.setLBarWidth = function (w:number) {
this.lBar.width = w;
}
I don't see a major problem in having the variable declared outside of the imageLoader function. If you were writing this in a class instead of the timeline then it would just be a class member variable and there is nothing wrong with that. They exist for this very reason.
If your deadset wanting to keep the loadBar variable local then you could always do this:
in the imageLoader function:
var loadBar:Loader Bar = new LoaderBar();
loadBar.name = "loadBar";
addChild(loadBar);
in the progressHandler function:
getChildByName("loadBar");
Since lBar (or loadBar for that matter) is an element that you need to manage at a class level, you should indeed make it a class member. There is nothing wrong with it ;)