Flash: Full window flash, and when minimum size scrollbars with SwfObject 2.0’s Dynamic Publishing
In the post "Elastic flash with scrollbars" a nice javascript library is presented to scale full window flash when the browser hits a certain. point. Worked great with SWFObject 1.0, but didn't work with SWFObject 2.0 and dynamic publishing without a tweak.
Here's the Javascript I'm using:
-
-
var params = {};
-
params.allowscriptaccess = "always";
-
params.menu = false;
-
var attributes = {};
-
attributes.id = "flashUI"; // what to call with External Interface
-
attributes.name = "flashUI";
-
swfobject.embedSWF("index.swf", "contentToReplaceDiv", "100%", "100%", "9.0.0", "expressInstall.swf", fv, params, attributes);
-
-
var scale = new FlashScaler("flashUI", 1280,768);
-
scale.resize();
This got the scaling to work but not on the original load, if the window was smaller than the minimum dimensions, as the load event has already been called. So I had to modify FlashScaler to call the resize function during constructor e.g.
-
-
function FlashScaler(flashdiv,w,h){
-
-
var flashObj = document.getElementById(flashdiv);
-
var minW = w;
-
var minH = h;
-
addWindowEvent("onload",resize);
-
addWindowEvent("onresize",resize);
-
resize(); //<-- added this line
-
.........
SWFForceSize is similar. "Size limiting for full window flash" Not exactly sure how they differ internally, but the approach that might work is hinted in the documentation and API But only when static publishing via the use of
-
-
swfobject.getObjectById(objectIdStr)
and perhaps passing it into SWForceSize? Don't know.
UPDATE: FlashScaler with this approach doesn't work with IE6, or IE7, gives script errors, looking into it.
Flash: Tip to find Clips lost in the library
If you have deeply nested folders in the library and/or drag things in from other Fla's you might not be able to find where they are. One tip is to find it, or drag it to stage from the other Fla and right click 'swap symbol' it will pop open the library viewer where it's at.
Flash: “Error initializing Java Runtime Environment - You may need to reinstall Flash.”
I've been trying to create a swf with about 100MB of uncompressed jpegs in it. Not surprisingly Flash opening it up expands to a whopping 1.5GB of ram, and then complains it ran out of memory during publishing it (even though the machine has 3GB of ram..), just prior to that it gives that error.
http://blog.tukker.org/2008/05/23/flash-cs3-error-initalizing-java-runtime-environment/
http://www.adobe.com/cfusion/webforums/forum/messageview.cfm?forumid=72&catid=612&threadid=1184131&messageid=4278084
This didn't make sense initially. But then I realized that adobe is likely using Java in the background to do the compilations, perhaps even embedding the FCSH., which would allow them to write the very difficult compiler in a cross platform way.
This might also explain why Flash (and Flex/Eclipse) hang for periods of time, as this is typical of garbage collection, and the larger the memory the longer it takes to do the sweep.
Flash: Error #1009: Cannot access a property or method of a null object reference.
Here's another needle, in the heap and stack.
If you have an array and you trace it out like so:
var ary:Array = [1,2,3]
trace(ary);// outputs 1,2,3
Behind the scenes, each element in the collection has it's toString() function before returning the single string. This is fine and good. However, if there is an error in that in the toString(), Even with debugging enabled, errors won't show up with a line number, leaving you head-scratching. In my case the toString function was overridden from a parent class, and didn't initialize variables due to missing a super() in the subClass's constructor.
Rants on Flash Player and Acrobat Reader
I starting web programming originally in Java, during it's heyday. Java had the grand vision "Write once, run anywhere" which turned into "Write once, test everywhere" with all the variances between different VM's and between upgrades. Ironically Java is still around, I still use it, and despite the massive increases in processor and memory, it's has grown in features to the point, developing with tools like Eclipse seem to be the same speed they were a decade ago. Sadly, flash appears to be following in it's footprints.
While this has been an amazing 2 years for flash, it's also been one of the most tumultuous..and the change appears to be going faster. In some ways every minor version of the flash player is more substantial in changes than some of the earlier major releases in lines of code (Just guessing). I often wonder why they bother calling it Flash player 9, when so many features changes, gaps and issues exist between minor versions, nad the transparent install still somewhat annoying on FireFox at least. Damn marketing people.
While I truly love aspects of flash, there are times like this when I feel like becoming a monk. One of the reasons I got into flash was I was tired of the issues between different browsers, now I'm not sure how much better we are. There have been nasty surprises where at times even Adobe's own components have been broken, but only on a specific minor version, and only when doing things like tweening Given the challenge in testing richly interactive sites, the visual nuances that are involved, having to test 8 minor verisons x 2 platforms x3-4 browsers by hand, really sucks ass.
I know from talking to the Flash Player QA team, they are doing I assume the best that can be done, they have a huge battery of Unit tests that are run regularly. But we rich media developers are a greedy lot. The features they are doing are exponentially more complex and they are facing the law of exponential growth....as the number of features are added, the possible interactions between them grows exponentially, and the normalization of the problems takes longer to stabilize... and this too sucks ass for us developing, I expect more quirks in the next year or two instead of less. Finding and working around quirks is about as much fun as peeling bubble gum out of kids hair. Toss in AIR growing pains, Flex considerations, and an already huge ecosystem of vastly different things and strategies calling themselves 'flash'. I know I'm having a hard time keeping track of just what features are supported, it's probably next to impossible task to keep things stable.
While I don't plan to give up on Flash. I actively loathe what Acrobat/PDF has become in the last year. Little pockets of the web, the Adobe browser...IMO trying to compete with IE, Netscape in a slightly subversive way. While I'm not a fan of HTML, right now using Adobe PDF on even basic PDF's has been a far worse experience than Browsers has ever been for me. Tons of hoops of fire for security and user preferences I don't care about. Bleh.
I've gone and only recommend people using FoxIt Reader which is faster, something like 1/10th size and ironically renders every PDF I"ve come across without problems where lately Adobe's version gives me more issues or actually crashes trying to read them...this latter I find completely mind blowing. For creating PDF's I find the PDF print driver from the PDF995 to be great, fast and friendly.
Like Flash (and AIR, and Flex..) I expect PDF's as a platform instead of document and viewer to solidify, but not anytime soon as they are still busy adding feature after feature. It's already taken about 1 year to shift gears into AS3.0 and gain about. I still have about 50% of my framework that has to be brought over. HOpefully this won't end up like the golden gate bridge in that when I get through converting it to AS3.0, that Flash 10 has come out and everything has to be redone again..
FlashRant: TypeError: Error #1006: value is not a function. *@#%!% !!
There are times when I really love flash, like the time I'm able to get something amazing done in a single day, that would take weeks to do in C++ or Java. Then like tonight, what starts out simple and should take just a few minutes, turns into an 10 hour excursion trying to figure out where a problem is, deciphering cryptic messages with no obvious relationship to what's going on. It's numerous of these experiences with flash's quirks that have resulted in me seriously contemplating becoming a monk.
Take this seemingly innocuous function:
-
-
function addTest(c:Class):void {
-
-
trace("addingTest ");
-
tests.push(c);
-
}
-
-
This is for a unit testing library I've developed for asynchronous tests. It neatly introspects a class for methods named a certain way and makes them into test cases. That works fine.
In the esoteric camp, trace isn't the normal trace. I override trace by making it a class variable, so I can point it to a external log (PowerFlasher's SOS) which has far better coloring, filtering, and searching than any other trace console I've seen. I do that like this earlier on.
-
-
public var trace:Function = TraceAdapter.NormalTracer();
-
This approach works fine everywhere, and I've been using it for months. However something about the overlap between the two cause the above error. When that's buried at the bottom of layers of code that normally works fine, it takes a long time to dig to find this needle in the heap and stack.
This is typical in much of the projects I end up with, where the issue is actually not a problem with either part but rather the interaction, making it very difficult to divide and conquer. The solution in this case, is in just that function to prohibit trace at all in that class..oddly in another almost identical class it doesn't have this issue!
Flash: Detecting the end of an animation
Say you have an animated character in a game, that others need to know when they are through playing their animation. Here are a few approaches:
Let's first assume we have a generic object named 'player_mc' that is our animation. We also have a centralized controller script closer to the root, that has a function like:
-
function onAnimationComplete(evt:Event = null):void{
-
//do something
-
currentPlayer = evt.target as MovieClip;
-
currentPlayer.gotoAndStop("still");
-
}
Note that we use evt = null just in case we want to use call the function without passing it an event.
1) Using addFrameScript
-
var init:Boolean;
-
if(!init){
-
/// !init check, this block is only needed when pasting on timeline
-
// to keep it from activating more than once when the movieClip recycles
-
addFrameScript(totalFrames -1, onAnimationComplete);
-
init = true;
-
}
-
-
Just remember if doing that approach, addFrameScript uses a frame number one less that what you see in Flash.
This approach is safer when indexing frame labels prior (e.g. with UIUtil) to map say a frame label of "AnimationFinishedFrame" to the frame number for addFrameScript to use.
-
addFrameScript(com.troyworks.ui.UIUtil.getNumberOfFrameLabel("AnimationFinishedFrame", onAnimationComplete);
-
2) Using Event Bubbling
Just communicate up the display list.
-
player.addEventListener("ANIMATION_COMPLETE", onAnimationComplete);
Then
-
//inside the player on last frame of the player animation
-
-
stop();
-
dispatchEvent(new Event("ANIMATION_COMPLETE", true, true));
For more info see here.
3) Use Singleton/Static or Stage as a message bus.
like 2 but using the stage or some other easy to access to communicate without bubbling.
4) Poll for Progress
This is a bit more work, but get's you the ability to find out more about the progress, eg. showing a progress bar for percentage played.
-
player.addEventListener(Event.ENTER_FRAME, onENTER_FRAME
-
-
function onENTER_FRAME(evt:Event):void{
-
var playermc:MovieClip = evt.target as MovieClip;
-
-
if(playermc.currentFrame == playermc.totalFrames){
-
onAnimationComplete();
-
}
-
}
Hope that helps.
Flash: Fast Prototyping and Sketching UI with FlowControl
While I enjoy the new power of Flash9/AS3.0, one of the things I really dislike about the AS3, is how much extra work to do basic things like setup buttons to do simple timeline control, this is especially hard on designers and animators who don't code. I agree with 5etdemi post 4 years ago, the basics have ironically gotten harder to do.
What wrong with ECMAScript/Actionscript? Well, it is not especially well suited for certain tasks, the worst of which is time-based/timeline-oriented animation and declarative drawing. I mean, it seems pretty ironic that ActionScript is derived from ECMAScript which was primarily oriented at scripting in a text-based environment, HTML and the DOM. Simply put, ActionScript has leaned more and more towards heavy lifting text operations (like RegEx and the new XML implementation) and less towards building programmatically what Flash was originally meant for, animation.
While there are useful utilities like Lee Brimelow's nice event generator utility, I wanted less, as even if being good with actionscript, when you have a few minutes to put together something for (or during!) a client/skype meeting, scripting isn't really an option. Thankfully AS3 has some tricks to help!
( press RIGHT arrow key to advance)
One tennant of Sketch is using the type and instance names to do most the event binding work, largely this is to allow Designers to stay on the timeline, but the same could apply to objects created in actionscript as well. So in the above example there are 2 scenes, and a bunch of empty frames, and a nav control. What's special is the buttons you see are actually just semi-transparent buttons (I call InvisiButtons) that have instance names like 'next', 'prev', (shown in the button names) there is no other script on the timeline for them. That via the FlowControl listening to ADDED event are autowired up to call 'nextFrame()' , 'prevFrame()' etc. These InvisiButtonscould be used as a hotspot over a comped image or basic text and wireframe graphics, allowing low to high fidelity comps to be created.
In this example a ENTER_FRAME event updates the TextField off to the right to show the current scene, frame et, to show where you are.
FlowControl has some other nifty features.
- optional features is the fadein, fadeout effect, with configureable color, so while there is a normal timeline, the fade effect is free and ads a bit of polish IMHO.
- tooltips telling you where the buttons go/do.
- keypress for left/right arrow to go to the next previous frame, escape to goto first frame-useful for slide shows
- XXX_autoBtn. If it sees this pattern that button will generate an XXX event (e.g. sayHi_autoBtn generates a new Event("sayHi"), which anybody is free to listen to.
All these are in the example (as well as all the code for FlowControl) on code.google.
Flow Control can be used 'embedded' as the document level class (or extending from it) or loaded as an external swf, and I'll be demoing that in the future. That latter feature is more targetted to creating highly skinnable games which I'll be covering in future blog posts.
Flash: Working with Events: Get on the bus..Bubbling is your friend.
One of the great changes in AS3 is the DisplayList. It when used appropriately, dramatically eases many things, one of my favorite is decoupling clip intercommunication, as the display list or any clip on it can act as a message bus.
Approach 1 : Display list heirarchy as message bus.
Say you have a monkey button shaped as a deep in a forest of tree graphics that you want to find out when it's been clicked on, even while it's jumping around from branch to branch (at different depths). If a event setup on the click is set to bubble it doesn't matter where or how deep it is, it will eventually bubble up to the parent class so you can do something with it.
Similarly say you have a animated figure that you want to fire off when it's completed with it's animation, to do something else. While one possibility is the 'controller' reaching down to watch (e.g. using ENTER_FRAME, or addFrameScript(totalFrames-1..), or the clip reaching up and telling the main timeline to do something. A much cleaner approach is listening for the event closer to the root (e.g. a document level class), and dispatching an event on the last frame like:
dispatchEvent( new Event("FINISHED_ANIMATION", true, true)); //last help it bubble
Approach 2: Stage as message bus.
Third is using a stage as a message bus, since every clip has access to it. Especially when used with the ADDED_TO_STAGE event and dynamically loaded assets that have to perform some functions before being ready or passing a set of values to a caring class, when using an event that can carry a generic message, like EventWithArgs.
Flash: View Controller binding
When using actionscript to turn a MovieClip , Sprite etc into a component. There are several points that can be used to introspect the children to bind the displayObject, whatever configuration is on stage, with the ActionScript class. Different binding points allow different things, here's the order and
OUTPUT:
- constructor: // displayObject children are already on stage in the displayList but haven' t been drawn yet. the Actionscript class for it is just getting instantiated.
- onFrame1: // actionscript on or associated with frame1 has fired
- activateHandler: //not always called
- onFirstFrameRender: //first time ENTER_FRAME has hit the frame1, meaning it's script has fired, and everything is already visible.
- renderHandler: //only if the stage.invalidate() is called.
-
package {
-
-
import flash.display.MovieClip;
-
-
import flash.display.Sprite;
-
-
import flash.display.StageAlign;
-
-
import flash.display.StageScaleMode;
-
-
import flash.events.Event;
-
-
import flash.text.TextField;
-
-
public class StageExample extends MovieClip {
-
-
public var sizeMe:MovieClip;
-
-
public var output_txt:TextField;
-
-
public var textLog:Array = new Array();
-
-
public function StageExample() {
-
-
super();
-
-
stage.scaleMode = StageScaleMode.NO_SCALE;
-
-
stage.align = StageAlign.TOP_LEFT;
-
-
stage.addEventListener(Event.ACTIVATE, activateHandler);
-
-
stage.addEventListener(Event.RESIZE, resizeHandler);
-
-
addEventListener(Event.ENTER_FRAME, onFirstFrameRender);
-
-
addEventListener(Event.RENDER, renderHandler);
-
-
addToLog("constructor: w " + stage.stageWidth + " h " + stage.stageHeight);
-
-
addFrameScript(0, onFrame1);
-
-
stage.invalidate();
-
-
}
-
-
private function onFrame1():void {
-
-
addToLog("onFrame1: w " + stage.stageWidth + " h " + stage.stageHeight);
-
-
//resizeHandler(event);
-
-
}
-
-
private function activateHandler(event:Event):void {
-
-
trace("onFirstFrameRender: " + event);
-
-
addToLog("activateHandler: w " + stage.stageWidth + " h " + stage.stageHeight);
-
-
//resizeHandler(event);
-
-
}
-
-
private function onFirstFrameRender(event:Event):void {
-
-
trace("onFirstFrameRender: " + event);
-
-
addToLog("onFirstFrameRender: w " + stage.stageWidth + " h " + stage.stageHeight);
-
-
// resizeHandler(event);
-
-
removeEventListener(Event.ENTER_FRAME, onFirstFrameRender);
-
-
}
-
-
private function renderHandler(event:Event):void {
-
-
trace("renderHandler: " + event);
-
-
addToLog("renderHandler: w " + stage.stageWidth + " h " + stage.stageHeight);
-
-
}
-
-
///////////////////////////////////////////////////////////////////
-
-
private function resizeHandler(event:Event):void {
-
-
trace("resizeHandler: " + event);
-
-
trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);
-
-
addToLog("resize: w " + stage.stageWidth + " h " + stage.stageHeight);
-
-
sizeMe.width = stage.stageWidth;
-
-
sizeMe.height = stage.stageHeight;
-
-
}
-
-
private function addToLog(str:String):void
-
-
{
-
-
textLog.unshift(str);
-
-
output_txt.text = textLog.join("\r");
-
-
}
-
-
}
-
-
}
