There are some challenges in Flash that are addressed with such regularity that it can be surprising that no uniform way of accomplishing these tasks has emerged. One of these challenges is dynamic flash movie resizing through JavaScript. While websites have been doing this for years and the techniques involved are simple, there are enough moving parts involved to make it a chore to recode and deploy every time you launch a new site. BrowserCanvas bundles all of the code necessary to do Flash resizing into a single ActionScript file which is easy to deploy and reuse. It takes care of a lot of the maintenance work necessary to do Flash JavaScript resizing so that it can be deployed with minimal effort.
The best part of BrowserCanvas is that it requires no external JavaScript in the page to function. Deployment involves putting a single Actionscript class into your classpath and adding a couple lines of code to your project. That’s it. There is no messing around with JavaScript imports, there are no extensive Actionscript libraries. It is as clean and simple as possible.
The following example shows you everything you need to do to randomly resize a flash movie every time the stage is clicked.
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import com.dncompute.canvas.BrowserCanvas;
public class DemoMain extends Sprite {
private var canvas:BrowserCanvas;
public function DemoMain() {
canvas = new BrowserCanvas(stage);
stage.addEventListener(MouseEvent.CLICK,randomSize);
}
public function randomSize(event:MouseEvent=null):void {
canvas.width = String( Math.random()*500 + 200);
canvas.height = String( Math.random()*500 + 200);
}
}
}
Below are links to different examples of BrowserCanvas in action. All of these examples are included in the browser canvas download file at the end of this post. You will note that none of these examples have additional javascript code embedded in them, all of the code is embedded in the Flash movie.
While using BrowserCanvas is really simple, the code itself does have a little bit of complexity to it. Unfortunately, simple and cross-browser are rarely in the same sentence.
I’ve tested BrowserCanvas in a variety of modern browsers on both OSX and Windows. I have not tested BrowserCanvas in any of the golden oldies (IE 5.5 or less, Firefox 1.5 or less, Netscape anything, Safari 2.0 or less, Opera 8 or less) and don’t plan to add support for them.
The execution speed seems to be incredibly slow in Safari, and min/max behavior in Safari seems to only work in the SWF Object version of my demos. For most applications this shouldn’t be an issue, but I plan to investigate this further if I find the time.
I also have not tested BrowserCanvas in sites with complicated CSS layouts and AJAX interaction. If you have issues in any current browser, I’d be eager to hear about them. BrowserCanvas attempts to do a bunch of clever things in JavaScript, but I wouldn’t be surprised if some of these tricks don’t work in a few fringe cases. You can turn the browser specific hacks off, this is discussed in the comments for the BrowserCanvas class.
Also note that if you want to run the examples locally, you may need to make changes to the Flash Player security settings. You can find instructions on how to do this half way down this article from Adobe . You can access the Global Security Settings Panel by doing the following:
Right Click Any Flash Movie > Settings > Privacy (Tab) > Advanced (Button) > Global Security Settings Panel (Link)
Packaging up Flash based components for use across a large variety of websites is a regular challenge for professional Actionscript developers. With the release of Flash 9, Adobe has made this easier to accomplish with innovations such as SWC Actionscript libraries. SWC libraries work well when you are deploying components which are self contained, but don’t cover situations where a component requires external elements such as JavaScript libraries. Documenting and deploying all of the various pieces necessary for a component like this can be an onerous task. I’ve often longed for a way to package all of a component’s various pieces together into a single, easy to deploy package.
One way to do this is to insert the JavaScript directly from Flash, rather than embedding it in the HTML page. I spent some time when Flash 9 was first released looking into ways to accomplish this. My understanding at the time was that ExternalInterface only worked to call existing JavaScript functions on the page, so I focused my JavaScript code insertion efforts on the use of navigateToURL("javascript:XXX"). While this technique works to a limited degree, I abandoned my efforts because I found the results incredibly unwieldy to use with large codebases.
However, I recently discovered an article devoted to JavaScript injection by Peter McBride. Mr. McBride has dispelled many of my misconceptions surrounding ExternalInterface. He also demonstrates some clever techniques for embedding JavaScript into your Actionscript code. I highly recommend Mr. McBride’s article, it is a thorough and easy to follow introduction to the JavaScript injection techniques used in BrowserCanvas.
Update 26 Feb 2009:
I recently updated this class to v2 which should correct the IE issues which some users noted in the comments below. Internet Explorer does not properly handle min/max settings on object tags. To work around this, browser canvas was reparenting the object tag and swapping it’s id. Unfortunately, changing the ID of an object appears to break Flash’s External Interface calls. I’ve adjusted the class to account for this. If you are not setting min/max sizes, I would also recommend that you simply turn this hack off altogether when instantiating the class.
Joe says:
Thanks, for sharing. I’ll check it out.
OpenRIA » Blog Archive » 在HTML页面中动态缩放flash的最佳方法 says:
[...] 以前曾经尝试过在html页面中让整个flash自己缩放自己,方法是利用javascript改变flash的所在的div宽度和高度,方法虽然可行,但是比较麻烦;现在终于发现了这个国外同行提供的解决方案,无需在html页面中写一行js代码,只需在flash中引入一个AS类即可,超级简单,超级强大,其原理是利用了javascript在actionscript中的代码注入功能,简单来说就是将js嵌入as中使用,实现了js和as的完美的契合! [...]
nant says:
thanks for sharing ,but when property “allowScriptAccess ” is set “never”,it will not work any more.
Noel says:
@nant – That is correct, thanks for clarifying this point.
Setting “allowScriptAccess” to “never” explicitly prevents Flash movies from being able to communicate with the browser, thereby preventing BrowserCanvas from making any changes to the Flash movie’s size.
Rob says:
In regards to the slow performance, have you tried wrapping the js calls in setTimeout(call, 0)? It effectively decouples the two runtimes and lets js run the call in a seperate thread so Flash doesnt lock up.
Pat says:
Hey thanks for the great example. Even though it wasn’t quite what I was looking for, I did learn quite a bit – thanks!
What I WAS looking for was a way to resize the elements inside the flash movie as I resize the browser. Ie: I have a full screen flash app that displays a large # (say for example the current time) I want it to be as large as possible, so if I maximize it takes up the whole screen. Any good URLs you can point me to to read? Thanks
Rob says:
@pat: http://board.flashkit.com/board/showthread.php?t=768235&highlight=stage
Noel says:
@Rob:
I did not try that, but I can see how that could be a great trick for making fast ExternalInterface calls where you either don’t care about the response or don’t need it immediately. Thanks for the tip.
@Pat:
All of the live examples you see on this site have “stage.scaleMode = StageScaleMode.NO_SCALE;” and “stage.align = StageAlign.TOP_LEFT;” set, which prevents the flash movie from scaling. If you comment the scaleMode line out, everything in the flash movie will start scaling out, which should make it behave in a manner similar to what you are requesting. I personally find the coordinate systems easier to work with when scaling is off (as well as avoiding half pixel issues) and if needed, I prefer to scale up in code.
If you only need to scale the movie full screen, and do not need to resize the movie at runtime, BrowserCanvas is probably overkill. You can make the Flash movie full screen through a few CSS/Object/Embed/SWFObject params, and all scaling/centering issues can be handled internally to Flash. BrowserCanvas is primarily aimed at those wishing to change SWF size during runtime.
deviation.de | Christian Klotz › BrowserCanvas says:
[...] light on BrowserCanvas yesterday. A really nice way to resize flash content dynamically via Actionscript. Give it a [...]
Miller Medeiros says:
very nice solution.. i didn’t tried to use it yet but it seems to be very nice.. principally because you can set the new size “on the go”..
i’ve made a solution for “full bleed” and “min/max size” based on javascript.. it’s called SWFFIT ( http://swffit.millermedeiros.com/ ) check it out later.. it’s not intended to work like your solution.. (i’ve made it to work only with 100% wid/hei flash movies..)
cheers and keep your good work..
doesnotcompute » BrowserUtil. An Actionscript Method for Getting the Value of an Object/Embed’s Id Attribute says:
[...] HTML page, there is no easy way to tell if you have the right one. In one of my previous projects, BrowserCanvas, I looked at the root URL in Flash and compared it to the URL assigned in the object/embed tag. [...]
Jim says:
license of source?
Noel says:
BrowserCanvas is under the MIT license. I believe it’s in the code itself, but I’ll add it into the post as well so it’s more clear.
2008/08/04 Daily Catch | 1983 | Catching design, since 1983 says:
[...] BrowserCanvas Dynamically resize your Flash canvas. [...]
Romu says:
Exactly what I needed for a special project. Very nice integration with SWFObject.
Thanks for sharing.
Romu
Shun Yi Chen says:
I am not very familiar with English, but when I found this article and read for a long time, I knew this is the information that I looking for.
Just thank for your sharing.
zuric says:
for example:
http://Domain_A/o.swf
is embeded in
http://Domain_B/o.html
is there any way to let the demo run when “allowScriptAccess ” is set to “samedomain”?
Ridimensionare un SWF in tempo reale — Tutorials Flash CS3 Flash CS4 says:
[...] L’ autore è Noel Billig. [...]
Resizing SWF at real time says:
[...] The author is Noel Billig. [...]
Adam Searle says:
We had problems using this. When browser canvas is combined with other ExternalInterface calls, we had lots of problems with IE bringing up errors. All good in safari and firefox. If we comment out the ExternalInterface calls inside BrowserCanvas all is well. Unfortunately even a simple, single ExternalInterface call will cause it to break
So.. dont combine your own ExternalInterface usage with browser canvas.
I am now looking for another way..
Simon de Turck says:
Hi there.
Why didn’t you use ExternalInterface.objectID to get the object or embed’s id? When i use 2 or more flash elements on a page using your script, it only alters the first one… looks like that’s the first node it encounters so it always returns that ID… ExternalInterface.objectID returns the id in context of the movie that asks for it!
This might even slim down the needed javascript as well.
Is there a reason for not using this?
Ian says:
It would be sweet if you would post links to the previous way of accomplishing this as well for comparison. :)
Saeid says:
When I load your canvasdemo03.html (using the link on your blog) in IE6.0 I get the following JavaScript error:
Line: 13
Char: 67
Error: Object doesn’t support this property or method.
Clicking 500×300 button after clicking 500×500 button or clicking them in reverse order doesn’t change the height of swf.
Here is a screenshot of the error:
http://saeid.fastmail.fm/files/temp/error.jpg
I would be grateful if you could give me some hints on how I can fix the error as I need to support IE6.0 for my project.
Thanks
Saeid
alltechneeds says:
Your class rocks~
Laurenţiu Lozan says:
There is a documented issue on Internet Explorer when the stage has stageWidth and stageHeight both zero at the beginning (unlike other browsers, in which these values are the correct ones from the start), and after one or more Event.RESIZE we get the right sizes.
Adding the following to the BrowserCanvas constructor in the place where _width and _height are set:
if(stage.stageWidth != 0 && stage.stageHeight != 0){
_width = String( stage.stageWidth );
_height = String( stage.stageHeight );
} else {
this.stage.addEventListener(Event.RESIZE, onResize_stage);
}
and the following function somewhere in the class:
private function onResize_stage(evt:Event):void {
if(stage.stageWidth != 0 && stage.stageHeight != 0){
_width = String( stage.stageWidth );
_height = String( stage.stageHeight );
this.stage.removeEventListener(Event.RESIZE, onResize_stage);
}
}
fixes the issue.
joshua says:
Hello, I’ve been using this class in one of my projects and recently ran into an issue with IE7 and flex deep linking. It turns out that flex deep linking is totally broken for IE7 in all the current SDK releases. However, there is a simple fix for the history.js file (see http://bugs.adobe.com/jira/browse/SDK-17197).
Now the problem is that BrowserCanvas somehow conflicts with deep linking in IE7 after the fix is applied. BrowserCanvas works properly but when it has been initialized deep linking breaks. Not getting any errors so it’s a bit mysterious at this point.
Send me a note if you want example code but it’s as simple as trying to use BrowserCanvas in conjunction with the test code supplied for Adobe bug 17197 linked above.
I’ll post back if we’re able to solve it. The workaround is to force a reload on URL change in IE7 which is the default behavior for IE6 (you can see how this works by examining history.js line 298 for flex SDK release 3.2.0 and noting the behavior for IE6).
Jesse says:
Just a followup to Joshua’s note– it looks like BrowserCanvas throws a javascript error in IE7, which would be harmless except that it prevents other javascript functions from getting called.
Even your examples on this page throw the error.
It looks like there are subtle issues with ExternalInterface on IE7
Noel says:
Hey everyone,
Thanks for comments, I finally had a chance to take a look at the IE issue and replaced the linked class with a new version. I’m not sure if it will fix everyone’s issues, but it should fix most of them. Let me know how it goes.
Thanks,
Noel
joshua says:
It works and I’m not seeing in js errors any more. However, flex deep linking still breaks on IE when BrowserCanvas is used. I’m not sure where the problem is but it wouldn’t surprise me if the bug is in ExternalInterface as Jesse suggests.
I don’t have a lot of time to spend on this now so we’re going with a workaround that forces IE to reload whenever the fragment changes. Not ideal, but workable.
Thanks!
Grump-Lab » Blog Archive » Resizing flash canvas dynamically in runtime says:
[...] Btw, you can download the Browser Canvas code here: http://www.dncompute.com/blog/2008/06/23/browsercanvas-the-worlds-easiest-way-to-dynamically-resize-... [...]
masu says:
Hi noel,
nice stuff … but your BrowserCanvas examples run pretty slow in Safari Version 3.2.1 (5525.27.1). I have Flashplayer version 9.0.124.0 installed. Is there anything I can do to speed up this app?
In Firefox version 2.0.0.20 this app works great!!!
Regards,
masu
Noel says:
Yeah, I noted the slow safari execution speed in the caveats section. My assumption is that external interface is simply slow in webkit browsers. At some point I’d like to benchmark this for confirmation and see if I can come up with some workarounds. There were some recommendations in the comments section I would like to look into.
Blenster says:
This may be a dumb question but I cannot figure this out. I’m trying to use this to control the size of a video player but it is scaling the entire stage rather than just showing or hiding a control that displays related videos, if any. If I have no other videos I’d like to resize the SWF so that the space normally used for additional video thumbnails doesn’t show up any longer, removing the empty space. The SWF stage resizes but the objects wthin also resize and I’m left with a smaller video player and the same blank space. Any ideas? I appreciate it.
Blenster says:
Turns out it is a dumb question… LOL I figured it out… I forgot to set:
stage.scaleMode = StageScaleMode.NO_SCALE;
And that does the trick. Doh!
easily resize flash stage dynamically: BrowserCanvas rocks « noah little says:
[...] BrowserCanvas rocks March 24, 2009 Over at doesnotcompute the headline reads: “BrowserCanvas. The World’s Easiest Way to Dynamically Resize Flash”. It’s [...]
Lara says:
Is it possible to do this in Action Script 2?
Noel says:
@lara This class isn’t available in ActionScript 2, but there are AS2 options for resizing Flash with JavaScript. My previous post on this topic touches on a few of the available options.
Alex says:
Hi! i am having an issue with IE. The BrowserCanvas doesn’t seem to work at all in any version of IE for me. I am trying to add an anchor to a page and i want the anchor to pop up after a couple seconds. Here is the code I am using:
import com.dncompute.canvas.BrowserCanvas;
var canvas:BrowserCanvas;
canvas = new BrowserCanvas(stage);
var timer:Timer = new Timer(1000, 5);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, anchorsAway);
timer.start();
function anchorsAway(e:TimerEvent):void
{
canvas.width = String(500);
}
Any suggestions?
Noel says:
@Alex – Does it work in other browsers, just not IE? If so, I would guess it’s a problem with how you embedded the Flash movie. Do you have it up on a site where in can be seen?
Alex says:
It seemed to work in FF on my test site but now that i made site live it doesn’t seem to work on any browser. It must be the way i am embedding the anchor. Here is the site: http://iq.glow.com/dms1062
Any suggestions would be much appreciated.
Noel says:
@Alex – I took a quick look at your page and it doesn’t appear that you have “id” params associated with your object/embed tags. This is going to be problematic as it will prevent the code from being able to properly identify the correct swf to resize. You can correct this by adding id params to your object tag, and an id property to your embed tag. The ids need to be different for each flash movie (and probably different for the object and embed tags as well). I would also recommend using a library such as swfobject to embed your flash in the page rather than inserting the code directly (Google even provides a url you can embed from so you don’t need a copy of the library on your own host).
The older version of this code library had a method for autocorrecting for this that I removed because it seemed overly complicated. If others are having this issue, I will consider putting it back in.
Alex says:
Ok…i am using the swfobject.js to embed the flash file but i am not seeing the browsercanvas work properly on any browser besides safari. Here is the link:
http://iq.glow.com/dms1062
Noel says:
I believe it will work if you use the “dynamic publishing method” of swfobject as opposed to the “static publishing method” (the tutorial on the swf object site gives step-by-step instructions for both methods). The issue appears to be with the double object parenting in the static publishing method. I’ll look into this further when I get a chance.
David says:
Great tool. Thanks for providing it.
Question: When you resize the canvas, x and y coordinates do not change. For example:
* Start with a 550 x 400 pixel movie.
* Expand it to 600 x 450 pixels.
* Attempt to place something at 0, 0 using DisplayObject.x and DisplayObject.y.
* Instead of being placed at the 0, 0 coordinates of the resized movie as you might expect, the item is placed at the 0, 0 coordinates of the originally sized movie, n pixels away.
Considering I’m a newbie at Flash I might just be doing the wrong thing. How can I position the object at the 0, 0 coordinates of the resized movie?
Justin says:
THX~~!
Bo says:
Hi ..
Great work .. But I can´t make it work i googleChrome. It simply dosent update.
Othervise the best solution I have come across
Cheers
/Bo
Sekhmet says:
This looks nice, but how do you actually implement it on your projects? I mean for the Actioscript newbies out there, me included ;)
Thanks!
Alex says:
Noel
for some reason i am not seeing the post i just made. If there is any chance you can just email me your response that would be great.
Thanks again!
Alex says:
Everything seems to be working great now except i am having an issue in IE. It seems as though the resize only happens once; if you refresh the page or come back to it from another page it will not work unless you clear your cache. This problem only seems to occur in Explorer though.
Alex says:
Here is the page with the problem”
iq.glow.com/dms1123/
Thanks again for all your help!!
Pavel says:
Hello,
this is really a great thing that has helped me a lot. But I am having problems using browser canvas in a swf that is loaded into another movie (preloader of course)… When I display the main content movie directly (dynamic publishing using swfobject), it works, it resizes itself just fine. If I load the preloader first, it doesn’t work (the main content movie is basically waiting for the ADDED_TO_STAGE event, and after catching it it initializes the browsercanvas object and goes on…) Like I said, loading this movie directly works, using preloader doesn’t. Is there a way to fix this, am I doing something wrong?
I can do the resizing in the preloader, yes, but that is not really elegant as I can’t listen to the content movie resize event, so I have to check its size periodically and that doesn’t seem right… Where the problem might be?
Thanks again for a great utility
Pavel
Pavel says:
Ah, nevermind, passing the id of the div container to the constructor seems to fix it… I guess I could pass it from the preloader as a URL parameter when loading the main movie… Nice stuff this BrowserCanvas thingy:)
Ludd says:
I’m using gaia 3.13 and i can’t get canvas broswer to work although gaia uses js/swfObject.js it doesn’t work. Object id in the html is written differently:
swfobject.embedSWF(”main.swf”, “flashcontent”, “100%”, “100%”, “10.0.0″, “expressInstall.swf”, flashvars, params, attributes);
the example files for canvasBrowser is:
<object id=”canvasdemo” width=”550″ height=”400″ classid=”…..
What can be done to fix this for Gaia 3.13 to accept it.
Thank you in advanced!