Can some one explain to me why the behavior of this ActionScript code is auto scale? - actionscript-3

I'm new to AS3 and I'm doing some custom video player video project for AIR. While I was studying the simple examples (non-StageVideo) on how to play videos, I've encountered a unique situation where I got an awesome auto-scaling (stretch-to-fit) to window behavior from Flash.
Whenever I set the SWF directive's width and height equal to the width and height of the flash.media.Video object I'm creating. It does the auto-scaling, stretch-to-fit, resizable behavior. Like so:
// SWF directive placed before the class declaration of the main class
[SWF( width="1024", height="576", backgroundColor="000000", visible="true" )]
// somewhere in my initialization
myvid = new Video();
with( myvid )
{
x = 0;
y = 0;
width = 1024; // if I set this wxh equal to wxh in the SWF directive it auto-scales!
height = 576;
}
myvid.attachNetStream( myns );
addChild( myvid ); // must come after instancing of video and netstream, and attach to make the auto-scale work
myvid.play( "somevideo.flv" );
Even if I set the width to 16 and height to 9 on both it scales and fits perfectly on the size of my window. Can some explain me this behavior? None of what I read in the documentation mentioned this.
Don't get me wrong, I like this behavior! :) It made things easier for me. But code-wise I need to understand why is this happening as the code I set had nothing to do with auto-scaling.
Also, what the heck are directives for? Don't they just have pure ActionScript 3 equivalent? They look hackish to me.

I think the behavior you're describing is caused by the scale parameter in the HTML embed of the Flash. Generally this defaults to showAll, scaling the Flash up to fit the container.
There are two different sizes: the size of the container (the block in the HTML page) and the size of the Flash content (what you specify in the SWF tag). The scale mode decides the behavior when these sizes don't match. You can control this behavior either by tweaking that embed parameter, or from AS3 directly using stage.scaleMode:
import flash.display.StageScaleMode;
// scale the content to fit the container, maintaing aspect ratio
stage.scaleMode = StageScaleMode.SHOW_ALL;
// disable scaling
stage.scaleMode = StageScaleMode.NO_SCALE;
If you want to use the scale mode to your advantage, I would set the width of your Video to match the stage dimensions like so:
myvid.width = stage.stageWidth;
myvid.height = stage.stageHeight;
This way you avoid having to repeat the SWF width and height.
The directives mostly specify some metadata or instructions for the compiler. The SWF tag in particular specifies the info in the SWF header, such as desired width, height, framerate. Mostly these are just some suggestions to the player + container about how the file should be displayed. Some of them can be changed in code (stage.frameRate = 50;). Another metatag is Embed, which will bundle some assets into the SWF (particularly handy if you want to embed some binary data).

Related

How to have an application to automatically scale when launched?

I want my application to automatically scale its size depending on the screen size. I want my application to fit any screen size automatically. I am making my application for mobile devices, how can I do this? I am fairly new at flash so please make it a bit simple!
Yes, there is no simple answer but the basics is:
stage.addEventListener(Event.RESIZE,onStageResize);
function onStageResize(e:Event):void {
// Use stage size for placing elements to their position..
// Position to left top
element1.x = 10;
element1.y = 10;
// Position to right top
element2.x = stage.stageWidth - element2.width - 10;
element2.y = 10;
// Position element to center and make it's width to scale with stage..
element3.width = stage.stageWidth - 20;
element3.x = 10;
element3.y = stage.stageHeight / 2 - element3.height / 2;
}
To scale elements place them inside on Sprite or MovieClip and scale that element like:
element.scaleX = 1.6; // scale 1 = 100% 2 = 200% etc
element.scaleY = element.scaleX;
I usually create public function "resizeElements(e:Event = null):void" for visual subclasses/components and call that from the main thread. In that function the object can resize it self.
In addition to #hardy's answer it's important to set the following variables on the stage:
// disables default 100% scaling of entire swf
stage.scaleMode = StageScaleMode.NO_SCALE;
// disables default align center
stage.align = StageAlign.TOP_LEFT;
Also, since the original question was regarding resize on launch, and this is mobile deployment it's important to call onStageResize(); once manually because the RESIZE event may not be fired initially. This would require changing:
function onStageResize(e:Event):void { ... }
to
function onStageResize(e:Event = null):void { ... }
Saying "automatically scale to screen" is too generic. The requirements this statement imposes is totally different between apps depending on what they need to do. There is no simple answer.
If your app has a main content canvas area, do you want to zoom to the content to fit the area? Do you want to keep the content the same size and show more of it? Maybe both - you could want to show more to a point, and then scale if there is still more room.
What do you want your UI to do? Dialogs could shrink/grow and remain central. Maybe you want to reflow them completely?
Do you have a slick UI? Maybe a menu with a set of buttons. Do the buttons need to be sized proportionally to the screen? What about the gaps between them? What if the screen ratio is different so if you scale them to fit they no longer work?
The point is, there isn't a simple answer. For basic layout there are UI frameworks that can assist you in placement and scaling, but you still need to decide how you want your app to behave. That totally depends on the app and what your intended design is.

CSS Aspect Ratio on Canvas

Recently, Mozilla launched a HTML5 game called Browser Quest. In the game, if you resized the window, the canvas would also resize.
I looked more into and I saw that it was beacuse of usign CSS3 Media Queries found here https://developer.mozilla.org/en/CSS/Media_queries
However, I still don't think I am doing it right. My canvas ID is #canvas. How would I go about putting it for my canvas?
my canvas specific width/height: height:352px; width:512px;
So you don't want to define size of a canvas in CSS since you will only ever be scaling it away from its "true" size. You always want to use the width and height attributes of the Canvas instead.
But that doesn't mean you can't define it's parent's size that way. Wrap the canvas in a div and set the div's CSS width/height to 100% (or whatever you please)
In code during setup you are going to have to do:
// javascript pseudocode
canvas.width = theCanvasParent.clientWidth; // or whatever attribute it is, I'd reccomend putting all of those things in one giant container div
canvas.height = theCanvasParent.clientHeight;
Since most browsers do not fire an event when the parent div changes size, you'll simply have to check, say, every half second with a timer to see if the div has changed size. If it has, then you resize the canvas accordingly.
However there is the onresize event, and depending on how your page is setup this may do the trick.
In Firefox, Opera, Google Chrome and Safari, the onresize event is fired only when the size of the browser window is changed.
In Internet Explorer, the onresize event is fired when the size of the browser window or an element is changed.
So if the only way to change your div's size is by changing the window's size, onresize will do you just fine. Otherwise you'll need a timer that constantly checks to see if the canvas size and div size are different (and if so, to resize the canvas).
A timer that constantly checks is what the Mozilla Bepsin team did (before Bespin became Skywriter and then merged with the Ace project, dropping all Canvas use)
Media queries won't provide you with the functionality you seek. Their purpose is simply to limit when a particular stylesheet is applied to a page.
Furthermore, the CSS width and height properties do not adjust the actual dimensions of canvas elements. Instead, they scale the element to the requested size. In your case, I'm assuming you want the canvas to actually be a different resolution. The resolution of the canvas is specified via the DOM width and height attributes on your <canvas> tag.
In order to handle resizing, you will need to use window.onresize to capture the resize event. Your canvas code will need to then create a new canvas at the desired size and properly copy over everything from the original canvas (when you resize a canvas object its pixel data is cleared).
As was yet pointed by Xenethyl, the most important point is to hook onresize so that you can adapt to your new canvas object size :
adjust the canvas dimensions (the drawing area dimensions) to the canvas rendering area (clientWidth and clientHeight)
take into account the new dimensions of the canvas for your drawing algorithms
redraw the canvas
You don't have to make a new canvas (which would force you to rehook other event handlers).
Most of the canvas in my web applications, in order to be perfectly adjusted to the window, are managed by a dedicated class whose skeleton is here :
function Grapher(options) {
this.graphId = options.canvasId;
this.dimChanged = true; // you may remove that if you want (see above)
};
Grapher.prototype.draw = function() {
if (!this._ensureInit()) return;
// makes all the drawing, depending on the state of the application's model
// uses dimChanged to know if the positions and dimensions of drawed objects have
// to be recomputed due to a change in canvas dimensions
}
Grapher.prototype._ensureInit = function() {
if (this.canvas) return true;
var canvas = document.getElementById(this.graphId);
if (!canvas) {
return false;
}
if (!$('#'+this.graphId).is(':visible')) return false;
this.canvas = canvas;
this.context = this.canvas.getContext("2d");
var _this = this;
var setDim = function() {
_this.w = _this.canvas.clientWidth;
_this.h = _this.canvas.clientHeight;
_this.canvas.width = _this.w;
_this.canvas.height = _this.h;
_this.dimChanged = true;
_this.draw(); // calls the function that draws the content
};
setDim();
$(window).resize(setDim);
// other inits (mouse hover, mouse click, etc.)
return true;
};
In your case I would create a new Grapher({canvasId:'#canvas'}) and the #canvas dimensions are defined in css (and usually adjust in complex ways to the available space).
The most interesting points are in the setDim function.

issues to change the height and width of swf in as3?

Hai am trying to add the height and width of swf dynamically but i cannot change stage.stageWidth and stage.stageHeight and also am tring with another method also.
[SWF( width="900", height="400")]
Its working fine but while adding the value dynamically it cannot change.
var hei:Number=500;
var wid:Number=300;
[SWF( width=wid, height=hei)]
The line
[SWF( width="900", height="400")]
is like telling the compiler to set properties for the SWF.
The variables you have written come into play only at runtime during which the compiler has no role to play. So basically, your code will be ignored.
You might want to have a look at this discussion here.

StageVideo displaying above content?

So I'm building a video player that appears in a nested (display) hierarchy, and I would really like an easy way to preserve the background. I have a Loader SWF that contains a bg, and another SWF (which contains the video player) that toggles between StageVideo and Video per the end user's environment. I have StageVideo working, but it always shows below other content.
Now I know that this is the desired behavior for StageVideo, as it allows the GPU to render content directly to the screen without having to composite the video feed with display list content (http://help.adobe.com/en_US/as3/dev/WSe9ecd9e6b89aefd2-68d5ef8f12cc8511f6c-7fff.html), but I really want to be able to show my background (if only as a 'picture frame') behind the video player. Drawing a simple rectangular frame around the player such that it appears to have a bg will not work; I need to be able to also display images and other DisplayObjects behind the video player itself.
Are there any scenarios in which this might be possible? Any potential workarounds (even undocumented) that someone has discovered to resolve this problem?
If all you need is a frame around the video player, try masking the background with a rectangle the size of the video screen and put it on top of it.
Otherwise you might have to use the regular video player instead of the StageVideo player.
Okay - got it. It turns out that putting all of the background content in a container, and masking the container with a frame-shaped mask will actually allow StageVideo to effectively render atop.
For example:
bg_container.x = video_container.x;
bg_container.y = video_container.y;
set_frame_mask(video_width, video_height, frame_width, bg_container);
// Helper function.
protected function setFrameMask(width:Number, height:Number, frame_width:Number, container:Sprite):void
{
var frame:Sprite = new Sprite();
frame.graphics.beginFill(0xFF0000);
frame.graphics.drawRect(0, 0, width, frame_width);
frame.graphics.drawRect(0, frame_width, frame_width, width - frame_width);
frame.graphics.drawRect(width - frame_width, frame_width, frame_width, height - frame_width);
frame.graphics.drawRect(frame_width, height - frame_width, width - 2 * frame_width, frame_width);
frame.graphics.endFill();
frame.x = container.x;
frame.y = container.y;
container.mask = frame;
}

Change Width/Height of SWF

I'm trying to edit an HTML that uses swfobject to load a flash file.
What I'm trying to do is to reduce the size of the SWF file.
I've tried editing the height and width parameter within the swfobject(), but that didn't work.
I tried reducing the width height in the HTML css, but that also didn't work..
How can I pass a 'width' or a 'height' parameter to the swfobject so it will actually load the swf in a smaller or 'zoomed out' way?
Thanks,
Depending on which version of swfobject, and which embed method you are using it may vary slightly, but in general a call to swfobject.embedSWF looks like this:
swfobject.embedSWF( "myMovie.swf",
"divIdToReplace",
"100%",
"900",
"9.0.0",
"expressInstall.swf",
flashvars, params, attributes
);
In this example I have set my width to 100% and my height to 900 pixels. If you are doing the embed in another way, post some code and perhaps I can help.
** NOTE **
Just because you can resize the container doesn't automatically mean you can "zoom out" on the swf. If the swf has "no scale" set, then instead of zooming out, you will just be cropping the swf.
** EDIT **
You can try setting the params object to include scale:"default", like this for example:
var params = {
menu: "false",
salign: "LT",
scale: "default",
quality: "high"
};
This is the params object you would pass into embedSWF like I have shown above.
You should create a container/wrapper for the SWF, set the width/height of the SWF to be 100%, then scale the container to whatever size you desire. This is covered in an older Stack Overflow post: Resize an SWF when loading it with SWFObject
Additional examples for using SWFObject and 100% scaling:
http://learnswfobject.com/advanced-topics/100-width-and-height-in-browser/