Let me explain my question a bit.
I am creating a flash website and I am using a small external preloader swf to load in the main swf. I have been able to get my preloader swf to take up the whole browser window but as soon as it loads in the main swf it only displays in its normal dimensions that it was built in.
I do have a resize listener within the main flash application and as soon as I change the size of the browser the main swf then occupies the whole browser. But how can I get it to start out that way?
-I've tried using an ENTER_FRAME handler but that broke some of my animations.
-I've tried setting the width and height of my loader object in the preloader and that doesn't seem to work either.
-I've also tried adding an ADDED_TO_STAGE listener to the loader, but that doesn't seem to have changed anything.
-I also tried having the preloader be in one scene and the main application be in another so that I was only loading one swf, but that didn't seem to work and I don't prefer that method of pre-loading.
I haven't been able to find a solution anywhere. Is there something easy that I'm missing? Let me know what you all think. preloader code is as follows:
import flash.net.URLRequest;
import flash.display.Loader;
import flash.events.Event;
import flash.events.ProgressEvent;
var request:URLRequest = new URLRequest("flashNew.swf");
var loader:Loader = new Loader();
loader.load(request);
this.addChild(loader);
function loadProgress(event:ProgressEvent):void
{
var percentLoaded:Number = event.bytesLoaded / event.bytesTotal;
var percentLoadedBar:Number = Math.round((event.bytesLoaded / event.bytesTotal) * 100);
percentLoaded = Math.round(percentLoaded * 100);
this.percentLoaded.text = String(uint(percentLoaded)) + "%";
progressBar.width = percentLoadedBar * 3.36;
}
function loadComplete(event:Event):void
{
//loader.content.height = stage.stageHeight;
//loader.content.width = stage.stageWidth;
}
function setDimensions(event:Event):void
{
loader.width = stage.stageWidth;
loader.height = stage.stageHeight;
}
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.contentLoaderInfo.addEventListener(Event.ADDED_TO_STAGE, setDimensions);
Is there a way I can change via javascript or something? I'm at a loss here and I've been stuck on this for hours. Any help would be appreciated. Thank you!
UPDATE
Here is my code for my resize function.
function resizeListener(e:Event):void
{
background_mc.width = stage.stageWidth;
background_mc.height = stage.stageHeight;
//The rest of the function is omitted. It is if's and else-if's that just reposition various elements.
//That's really all this function does is re-position elements with the exception of the above code which resizes the background.
}
Here is the event listener call.
stage.addEventListener(Event.RESIZE, resizeListener);
Try this:
removed this line of code: this.addChild(loader);
then tweak your loadComplete function to this:
function loadComplete(event:Event):void
{
addChild(loader.content);
loader.content.height = stage.stageHeight;
loader.content.width = stage.stageWidth;
}
Related
Im working on a banner for google double-click studio. My parent swf loads a child swf and adds it to the stage. I need to get access to the parent swf stage from my child. How would i do that?
This is my parent code
import com.google.ads.studio.HtmlEnabler;
import com.google.ads.studio.events.StudioEvent;
import com.google.ads.studio.display.StudioLoader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.MovieClip;
var enabler:HtmlEnabler = HtmlEnabler.getInstance();
enabler.init(this);
var loadedHandler:Function = function(event:StudioEvent):void {
var myLoader:StudioLoader = new StudioLoader();
var req:URLRequest = new URLRequest("child.swf");
myLoader.load(req);
holder.addChild(myLoader);
}
My child swf has a document class where i want do access the stage.
the problem is:
_enabler = new ProxyEnabler();
stage.align = StageAlign.TOP_LEFT;
On stage i get: #1009: Cannot access a property or method of a null object reference.
Anyone know how to solve this?
this.parent.stage should do the trick. Make sure you use it after the child has been added to the parent/stage. Note: You could just move the stage.align = StageAlign.TOP_LEFT; to the parent if you don't need a different setting.
Wanted to give my own two cents on this piece. I tried the other answer but it didnt work. I got in touch with Doubleclick Support and they gave me an answer that worked out perfectly. In this example i am creating a stage mouseover and mouseout event handler.
In your example you would change
stage.align = StageAlign.TOP_LEFT;
to be
this.addEventListener(Event.ADDED_TO_STAGE, isAddedToStage);
function isAddedToStage(e){
stage.align = StageAlign.TOP_LEFT;
}
And here is my example with a stage mouseover and mouseout event handler.
this.addEventListener(Event.ADDED_TO_STAGE, isAddedToStage);
function isAddedToStage(e){
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
}
function mouseMoved(evt:Event):void
{
//custom script here
mouseIsOver = true;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeft);
}
function mouseLeft(evt:Event):void
{
//custom script here
mouseIsOver = false;
stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeft);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
}
I'm trying to load and unload many external swf files into main blank swf. And use navigation buttons (next/back) that located on the externally loaded child pages to navigate (load and unload pages).
I tried to dispatch event from child to main to unload. It works fine only with the first page, as the dispatcher is bubbling only once.
I have a default page to be loaded and dispatcher listener at the main swf as follows:
var cont:Sprite= new Sprite();
var swfLoader:Loader = new Loader();
var swfFile:URLRequest = new URLRequest("Page1.swf"); //default page
addChild(cont);
swfLoader.load(swfFile);
cont.addChild(swfLoader);
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoadedHandler);
function swfLoadedHandler(event:Event):void {
MovieClip(event.currentTarget.content).addEventListener("eventTriggered", removeLoader);
}
function removeLoader(event:Event):void {
SoundMixer.stopAll();
this.swfLoader.unloadAndStop();
this.removeChild(cont);
this.cont = null;
swfLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, swfLoadedHandler);
trace ("dispatched");
}
Also the next button code on child page1.swf is as follwos:
nxt_pg.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler_8);
function fl_MouseClickHandler_8(event:MouseEvent):void {
content_mc.gotoAndStop(1);
dispatchEvent(new Event("eventTriggered", true));
SoundMixer.stopAll();
//Code of Loading new page here
}
And the same code for back button.
So, I wonder if anyone could help me with code or better technique..Thanks in advance fore your help.
I worked around this by removing Next and Back buttons from child SWFs and put it on container inside movie clip and change its visibility as needed.
At index page (page0.swf) I simply set 'buttons_mc.visible = false;' and make it visible at rest of pages.
The most important thing here is using 'addChildAt(myLoader,0)' instead of 'addChild(myLoader)' to make the buttons movie clip on top of the loaded SWFs.
All this done only on container code and no need to do any extra coding with the external loaded SWFs.
Below is the code for the container swf:
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.MouseEvent;
var swfNumber=0;
var myLoader:Loader = new Loader();
var myRequest:URLRequest = new URLRequest("swf/"+"Page"+swfNumber+".swf");
buttons_mc.visible = false;
myLoader.load(myRequest);
addChildAt(myLoader,0);// will be added under the buttons layer
trace(getChildIndex(myLoader));
//==============
buttons_mc.nxt_pg.addEventListener(MouseEvent.CLICK, nextSwf);
function nextSwf(event:MouseEvent){
if(swfNumber<totalSwf){swfNumber++}
else (swfNumber=0);
reload();
trace("Next");
}
buttons_mc.prv_pg.addEventListener(MouseEvent.CLICK, previousSwf);
function previousSwf(event:MouseEvent){
if(swfNumber>1){swfNumber--}
else (swfNumber=0);
reload();
trace("Back");
}
//==============
function reload(){
if (swfNumber==0){buttons_mc.visible = false;}
else (buttons_mc.visible = true);
myLoader.unloadAndStop();
removeChild(myLoader);
myRequest= new URLRequest("swf/"+"Page"+swfNumber+".swf");
myLoader.load(myRequest);
addChildAt(myLoader,0);
}
I'm having an issue with playing an external SWFs inside the main SWF. Everything loads great, except not on cue. I'm using a simple delay actionscript to pause the main timeline until the external SWFs load, but it doesn't always sync up when testing in browsers.
Is there an AS3 code that I can use to pause the main timeline until the external SWF is finish loading and playing?
I need to do this multiple times through the movie, btw...
Below is the delay and the loadmovie array I'm using.
<--------------//Timer//--------------->
var timer4:Timer = new Timer(1500, 1);
timer4.addEventListener(
TimerEvent.TIMER,
function(evt:TimerEvent):void {
play();
}
);
timer4.start();
<--------------//loadMovie//--------------->
function startLoad()
{
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest('flip/note_flip.swf');
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler);
mLoader.load(mRequest);
}
function onCompleteHandler(loadEvent:Event)
{
addChild(loadEvent.currentTarget.content);
}
function onProgressHandler(mProgress:ProgressEvent)
{
var percent:Number = mProgress.bytesLoaded/mProgress.bytesTotal;
trace(percent);
}
startLoad();
The load() method of the loader object is asynchronous. It means that the process will continue to execute next lines of code and loading is done independently. That's why you can see it's not on cue.
The simple way to fix your problem is to stop() all the loaded movies upon Event.COMPLETE and play() them once all the movies are loaded.
Use an array to store the loaded movies and address them once all movies are loaded.
And yeah, the timer hack is pointless, you won't know how long it will take the file to load, it can be different every time.
EDIT:
Let's assume that you've got N movie .swf files that makes a complete scene. You would like to load all of them, and once they're all loaded - play them.
Let's build a simple step-by-step logics:
1) First of all, we need a list of the URL pointing to where the external SWFs are.
2) Then we want to start loading the SWFs one by one (and not altogether) to prevent Flash Player bug of not loading some of the content AND keeping the order of movie clips aka z-index, depth, layer order etc.
3) On each loaded movie we count how many are still left to be loaded.
4) Once all movies are loaded, we play() all these movies.
Here's the code for you (written in a frame in case if you're not using classes and not familiar with OOP):
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
var linkArray:Array = ["1.swf", "2.swf", "3.swf"];
var loadedMovieArray:Array = [];
var totalMovies:int = linkArray.length;
var loadedMovies:int = 0;
var urlRequest:URLRequest = new URLRequest();
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, onMovieLoaded);
loadMovies();
function loadMovies():void
{
var movieIndex:int = loadedMovies;
var movieURL:String = linkArray[movieIndex];
urlRequest.url = movieURL;
l.load(urlRequest);
}
function onMovieLoaded(e:Event):void
{
var loadedMC:MovieClip = l.content as MovieClip;
loadedMC.stop();
loadedMovieArray.push( loadedMC );
loadedMovies++;
if (loadedMovies == totalMovies)
onAllMoviesLoaded();
else
loadMovies();
}
function onAllMoviesLoaded():void
{
for (var i:int = 0; i < loadedMovieArray.length; i++) {
var mc:MovieClip = loadedMovieArray[i];
addChild(mc);
mc.play();
}
}
I know there are a lot of previous topics about preloaders and I've tried to follow every one of them but I still get the same problem (well they have helped me go from 80% -> 50%)
Right now it starts at 61450 / 125207 which is about 50%.
Here is my Main Document (default class file for the entire project) class:
public class MainDocument extends MovieClip
{
private var preloader:Preloader;
private var sB:startButton;
public function MainDocument()
{
preloader = new Preloader();
preloader.x = 300;
preloader.y = 400;
addChild(preloader);
loaderInfo.addEventListener(Event.COMPLETE,addStartButton,false,0,true);
}
private function addStartButton(e:Event):void
{
sB = new startButton();
sB.x = 300;
sB.y = 450;
sB.addEventListener(MouseEvent.CLICK,sMainMenu,false,0,true);
addChild(sB);
loaderInfo.removeEventListener(Event.COMPLETE,addStartButton);
}
private function sMainMenu(e:Event):void
{
sB.removeEventListener(MouseEvent.CLICK,sMainMenu);
removeChild(sB);
removeChild(preloader);
sB = null;
preloader = null;
var menuScreen = new MenuScreen();
addChild(menuScreen);
//I have heard that the following code might work better:
//var menuScreen:Class = getDefinitionByName("MenuScreen") as Class;
//addChild(new menuScreen() as DisplayObject);
}
}
And the Preloader that it attaches:
public class Preloader extends MovieClip
{
public function Preloader()
{
addEventListener(Event.ENTER_FRAME,Load);
}
private function Load(e:Event):void
{
//"bar" is a movieclip inside the preloader object
bar.scaleX = loaderInfo.bytesLoaded/loaderInfo.bytesTotal;
//"percent" is a dynamic text inside the preloader object
percent.text = Math.floor(loaderInfo.bytesLoaded/loaderInfo.bytesTotal*100)+"%";
trace(loaderInfo.bytesLoaded+" / "+loaderInfo.bytesTotal);
if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal)
{
removeEventListener(Event.ENTER_FRAME,Load);
}
}
}
-> Nothing is set to Export on Frame 1 except for the Preloader
-> No objects exist on the first frame; the only code on first frame is stop();
-> I placed a copy of every single MovieClip in the second frame and when the startButton is clicked, a gotoAndStop(3); is run so no one ever sees frame 2.
If anyone knows of anything simple that I could have forgotten, please let me know!
Thanks!
You're tying to use a preloader in the file being preloaded. In that case, there is going to be bloat from the rest of the project's code and assets. The reason you are seeing your preloader seemingly delayed is because a swf must load completely before any code will execute. This includes all assets on stage regardless of what frame they are on, even if you have settings in place to export on something other than frame 1. Instead, try using a blank shell as your preloader. This shell will have nothing in it but the loader code and a preloader graphic or animation. When the load is finished, hide your preloader and add your loaded content to the stage of the shell, or a container movieclip in the shell.
All the following code goes in your shell, which is just another FLA file with nothing in it but this code, and a preloader bar. The dimensions of this file should be the same as the file you are loading into it, ie your original swf file you were trying to preload.
Use it by calling loadSwf( "mySwfNameOrURLToSwf.swf" );
The variable _percent will populate with the current load percentage, which you can correspond to your loading bar scale. Presuming the preloader bar is named "bar", the line bar.visible = false; in the onSwfLoaded function will hide it. addChild( _swf ) adds the loaded swf to the shell's stage. The line _swf.init(); references a function in the loaded swf you will need to add called init() that starts your loaded swf doing whatever it is its supposed to do. Have everything in the loaded swf start on the first frame now, including the init() function.
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.SecurityDomain;
import flash.system.LoaderContext;
import flash.system.Security;
import flash.events.Event;
import flash.events.ProgressEvent;
var _swfLoader:Loader;
var _swf:DisplayObject;
var _percent:Number;
function loadSwf( swfURL:String ):void
{
_swfLoader = new Loader();
var req:URLRequest = new URLRequest( swfURL );
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.applicationDomain = ApplicationDomain.currentDomain;
loaderContext.checkPolicyFile = true;
_swfLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onSwfProgress);
_swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSwfLoaded);
_swfLoader.load(req, loaderContext);
}
function onSwfProgress( evt:Event ):void
{
_percent = Math.round( ( evt.target.bytesLoaded / evt.target.bytesTotal ) * 100 );
}
function onSwfLoaded( evt:Event ):void
{
_swfLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onSwfProgress);
_swfLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onSwfLoaded);
_swf = _swfLoader.content;
addChild( _swf );
bar.visible = false;
_swf.init();
_swfLoader = null;
}
your code looks ok.
when you are not on a http server, loading process are simulated.
After compiling, press crtl + B.
In menu you can choose the downloading speed and simulate a download by pressing again ctrl+enter.
it might help you to debug your preloader
#Lee Burrows What you said was right but would have been better if you looked at what I mentioned at the end of the code (three bold points)
The solution I used was:
-> I set everything to Export on Frame 2 on my 3 frame document.
-> Removed everything on Frame 2
-> Created a TextField via constructor and used drawRectangle for loading bar
-> No movieclips present on frame 1, and used
var menuScreen:Class = getDefinitionByName("MenuScreen") as Class;
addChild(new menuScreen() as DisplayObject);
instead of the previous code.
The reason why what I had originally didn't work because, as Lee Burrows mentioned, the Export for Actionscript hangs the loading if X = 1 in Export on Frame X, regardless if Export on Frame 1 was checked or not. Changing it to 2 or unchecking Export for Actionscript were the two solutions (except if it isn't exported for actionscript, then its code cant be referenced to).
Preloader starts at about 2% now.
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);
}