AS3: How to print a full page Movieclip? - actionscript-3

I am trying to print a movieclip on a button click. The movieclip originally is 300 x 400. I want to scale the movieclip to the highest size possible within the page and then print it.
Currently, I can print the movieclip using the following :
on(release)
{
var pj:PrintJob = new PrintJob();
pj.start();
pj.addPage(my_mc);
pj.send();
}
Thanks

You can first scale the movieclip so its size matches the maximum width and height of the page:
my_mc.width = pj.pageWidth;
my_mc.height = pj.pageHeight;
This will stretch the movie clip however, so to fix that we set the scale of both x and y to the smallest scale:
my_mc.scaleX = my_mc.scaleY = Math.min(my_mc.scaleX, my_mc.scaleY);
Final code:
var pj:PrintJob = new PrintJob();
pj.start();
var printArea : Rectangle = new Rectangle(0, 0, my_mc.width, my_mc.height);
my_mc.width = pj.pageWidth;
my_mc.height = pj.pageHeight;
my_mc.scaleX = my_mc.scaleY = Math.min(my_mc.scaleX, my_mc.scaleY);
pj.addPage(my_mc, printArea );
pj.send();

Related

Auto size text field with Actionscript 3

I am not sure if this is possible, so, please, help me out a little bit over here:
I have an image loaded into the stage:
var miC:Loader = new Loader();
miC.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
miC.load(new URLRequest("coverph.jpg"));
function onComplete(e:Event):void {
miC.width = stage.stageWidth;
miC.height = stage.stageHeight;
miC.x = 0;
miC.y = 0;
addChild(miC);
trace(miC.width, miC.height);
}
And this way the image auto size itself to perfectly match the screen resolution (I have tried it with: (all in landscape)
960dp x 720dp
640dp x 480dp
470dp x 320dp
426dp x 320dp
1196dp x 720dp
and 720dp x 720dp
They all worked fine (it won´t go over 735)
Now, my question is... let´s say that for the 1196 x 720 I have a textField, a textFormat and a legend that appears on the top of the screen (as a title):
var fmat:TextFormat = new TextFormat();
fmat.font = "Times New Roman";
fmat.size = 105;
fmat.color = "0xFF0000";
var titulo:TextField = new TextField();
titulo.x = 145;
titulo.y = 30;
titulo.width = 1290;
titulo.height = 122,10;
titulo.defaultTextFormat = fmat;
titulo.antiAliasType = AntiAliasType.ADVANCED;
titulo.text = "THE TITLE OF WHAT IM DOING";
addChild(titulo);
How do I (if possible) auto size the textField and format to keep the same proportion according to the screen resolution?
Try something like this..
titulo.autoSize = "left";
titulo.text = "THE TITLE OF WHAT IM DOING";
var txt_holder:Sprite = new Sprite();
txt_holder.addChild(titulo);
stage.addChild(txt_holder);
stage.addEventListener(Event.RESIZE, onStageResize);
function onStageResize(e:Event):void {
txt_holder.width = stage.stageWidth * 0.8; // 80% width relative to stage
txt_holder.scaleY = txt_holder.scaleX; // To keep aspectratio
txt_holder.x = stage.stageWidth / 2;
txt_holder.y = 10;
}
With a few extra settings in your app you could calculate what the scaling factors should be for the x-axis and y-axis based on what the resolution is and then set the scalex and scaley properties of the TextField.
Reference: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html#propertySummary

How do you add stroke to text in a GPU rendered Mobile app? [duplicate]

Unfortunately the filters do not work (drop shadow, glow) in GPU mode. I'm looking for an opportunity to use these effects to text in this mode. I will welcome any advice.
As Astraport mentions, you'll need to draw the textfield out to a bitmapData every time you update the text using bitmapData.draw().
If you use textField.getBounds to determine the size of the bitmapData you need, the resulting bounds rectangle will not include the extra size due to the filter (e.g. a DropShadowFilter sticks out the side of the textbox by certain pixels depending on the 'distance' and 'blur'). To ensure that you include the filters when you draw the bitmap, you'll also need to use bitmapData.generateFilterRect() to get the correct size rect.
Code snippet (untested, but general idea):
// Remember the transform matrix of the text field
var offset : Matrix = myTextField.transform.matrix.clone();
// Get the bounds of just the textfield (does not include filters)
var tfBounds : Rectangle = myTextField.getBounds( myTextField.parent );
// Create a bitmapData that is used just to calculate the size of the filters
var tempBD : BitmpaData = new BitmapData( Math.ceil(tfBounds.width), Math.ceil(tfBounds.height) );
// Make a copy of the textField bounds. We'll adjust this with the filters
var finalBounds : rectangle = tfBounds.clone();
// Step through each filter in the textField and adjust our bounds to include them all
var filterBounds : rectangle;
for each (var filter : BitmapFilter in myTextField.filters) {
filterBounds = tempBD.generateFilterRect( tfBounds, filter );
finalBounds.left = Math.min( finalBounds.left, filterBounds.left );
finalBounds.right = Math.max( finalBounds.right, filterBounds.right );
finalBounds.top = Math.min( finalBounds.top, filterBounds.top );
finalBounds.bottom = Math.max( finalBounds.bottom, filterBounds.bottom );
}
// Now draw the textfield to a new bitmpaData
var textFieldBD : BitmpaData = new BitmapData( Math.ceil(finalBounds.width), math.ceil(finalBounds.height) );
offset.tx = -finalBounds.x;
offset.ty = -finalBounds.y;
textFieldBD.draw( myTextField.parent, offset, myTextField.transform.colorTransform );
// Create a bitmap and add the bitmap data. Note: normally you would create a
// bitmap once and just update the bitmpaData
var bitmap : Bitmap = new Bitmap();
myTextField.parent.addChild( bitmap );
// Position the bitmap in same place as textField
bitmap.bitmapData = textFieldBD;
bitmap.x = myTextField.x - finalBounds.x;
bitmap.y = myTextField.y - finalBounds.y;
myTextField.visible = false;
Here is how to convert ANY DisplayObject to a Bitmap - useful for "restoring" filter effects in AIR GPU mobile rendermode. This is Pixelthis's solution, fixed, optimized and tested:
// => 'bitmap' must belong to the same parent as 'obj'. 'obj' should be invisible.
static public function Update(obj:DisplayObject, bitmap:Bitmap):void {
//trace("CacheToBmp",obj.name);
// Remember the transform matrix of the text field
var offset:Matrix = obj.transform.matrix.clone();
// Get the bounds of just the textfield (does not include filters)
var bounds:Rectangle = obj.getBounds(obj);
// Create a bitmapData that is used just to calculate the size of the filters
var tempBD:BitmapData = new BitmapData( Math.ceil(bounds.width), Math.ceil(bounds.height), false );
bounds.width = obj.width;
bounds.height = obj.height;
// Make a copy of the textField bounds. We'll adjust this with the filters
var finalBounds:Rectangle = new Rectangle(0,0,bounds.width,bounds.height);
// Step through each filter in the textField and adjust our bounds to include them all
var filterBounds:Rectangle;
for each (var filter:BitmapFilter in obj.filters) {
filterBounds = tempBD.generateFilterRect( tempBD.rect, filter );
finalBounds = finalBounds.union(filterBounds);
}
finalBounds.offset(bounds.x,bounds.y);
finalBounds.x = Math.floor(finalBounds.x);
finalBounds.y = Math.floor(finalBounds.y);
finalBounds.width = Math.ceil(finalBounds.width);
finalBounds.height = Math.ceil(finalBounds.height);
// Now draw the textfield to a new bitmpaData
var data:BitmapData = new BitmapData( finalBounds.width, finalBounds.height, false, 0 );
offset.tx = -finalBounds.x;
offset.ty = -finalBounds.y;
data.drawWithQuality( obj, offset, obj.transform.colorTransform, obj.blendMode, null, true, StageQuality.HIGH );
bitmap.bitmapData = data;
// Position the bitmap in same place as 'obj'
bitmap.x = obj.transform.matrix.tx + finalBounds.x;
bitmap.y = obj.transform.matrix.ty + finalBounds.y;
}
The basic idea is to apply the filters as normal and then draw the display object to a bitmapdata and add the bitmap to the stage. See http://forums.adobe.com/message/3934192 for an example.
If the text that you are applying this to is static it should be easy enough to do, but if you want to apply this dynamic text (for example, a score counter that will change frequently, or text that is user-editable) I imagine it may start to get annoying, but I don't know of any other solution.

AS3 flash CC I want to set the width of the parent Movieclip of a Textfield

I have dynamically created a bunch of textfields, the number of which depends on xml input. The textfields need to be button-enabled, so I thought the easiest solution is to put them in a movieclip and buttonMode that movieclip.
The hierarchy looks like this: main (extends MovieClip) -> klankoefening (a MovieClip) -> Textfieldparent (a MovieClip) -> Textfield
I have a variable maxw which contains the biggest textfield's width and I want all my Textfieldparents to have this width.
I'm trying to do it like this:
//generate textfields
keuzes = new XMLList(lijstOpties.categorie.(#cat == catname));
var nrs:int = keuzes.keuze.length(); //aantal keuzemogelijkheden
var maxw:int = 0; //grootste breedte tf, nodig voor bepalen breedte knoppen
for (var nr:int = 0; nr < nrs; nr++) {
var tf:TextField = createTextfield(werkfmt);
tf.text = keuzes.keuze[nr].toString();
tf.autoSize = "center";
tf.background = true;
tf.backgroundColor = 0xffcc33;
tf.border = true;
tf.borderColor = 0x000000;
tf.name = "keuzetf";
tf.selectable = false;
tf.x = 0;
tf.y = 0;
if (tf.width > maxw) {maxw = tf.width;}
var tfcontainer:MovieClip = new MovieClip();
tfcontainer.buttonMode = true;
tfcontainer.name = keuzes.keuze[nr].toString();
tfcontainer.addChild(tf);
klankoefening.addChildAt(tfcontainer,nr);
}
for (var an:int = 0; an < 3; an++) {
var mcs:MovieClip = klankoefening.getChildAt(an) as MovieClip;
mcs.width = maxw;
trace ("mcs " + mcs.width);
var mtf:TextField = mcs.getChildAt(0) as TextField;
trace ("mtf " + mtf.text);
}
the trace results are
mcs 32.05
mcs 33
mcs 21.25
Which I find odd, because I stated in my second loop that the width for all Textfieldparents should be set to maxw. What is happening?
Consider drawing an underlaying Rectangle of desired width and height. You can use mcs.graphics to do that. The trick is, width of a DisplayObjectContainer is a calculated property, and changing it will likely result in changing scale. Say, a MC has two shapes as chilren, one at (1000,0) and another at (0,0), and both have width of 10 - the resultant width of that MC will be 1010. So, instead of changing width, simulate its change by drawing a rectangle on the MC.
mcs.graphics.clear();
mcs.graphics.lineStyle(0,0,0);
mcs.graphics.beginFill(0x808080,0); // bogus filled rect, to capture events
mcs.graphics.drawRect(0,0,maxw,maxh); // height is needed too
mcs.graphics.endFill();
After thinking a bit more about your problem, I think your issue is that the buttons you're adding the text to have a width entirely defined by the TextField, and because you're set the text to autoSize, it's snapping back to it's original width.
What you will need to do to make the width more indicative of what you need, and allow for easy clicking on the buttons is to create a transparent rectangle in the tfContainer mc, set the width of the tfContainer, and then add the text to the button.

MovieClip disappear after changing width and height in AS3

I am trying to load an image from an url in as3, as follows:
var myImageLoader:Loader = new Loader();
private var mcImage: MovieClip = new MovieClip();
var myImageLocation:URLRequest = new URLRequest("http://example.com/xyz.jpg");
myImageLoader.load(myImageLocation);
mcImage.addChild(myImageLoader);
mcImage.x = 100;
mcImage.y = 100;
//mcImage.width = 50;
//mcImage.height = 50;
addChild(mcImage);
The code above works fine, but since my desire image has a different size comparing to the original image, changing its size is necessary here. So after using the lines, which are commented in the code above, the mcImage disappear.
I tried to use mcImage.scaleX =myImageLoader.width/50 , but since myImageLoader is not loaded at the beginning, we cannot get the width of myImageLoader which is null.
It's the often error with setting sizes, you can't set size of empty display object (object that width and height are zero). To set size of display object you need first to draw something on it's graphics (for example 1*1 px rectangle), but you should understand that after it you will just scale your display object relatively to it's original size, for example if you draw 1*1 px rectangle and set with=height=50, scaleX and scaleY for it will be 50, so your loaded image if we say about loader will be giant size :) It's all about sizing in flash.
What about your task: there is one common rule - don't resize loader, resize loaded image. As I said above resizing of loader will only scale your image rather than set it sizes. Add complete handler and resize loader.content as you want.
Example:
public function astest()
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplte);
addChild(loader);
loader.load(new URLRequest("https://www.google.ru/images/srpr/logo3w.png"));
}
protected function onComplte(event:Event):void
{
EventDispatcher(event.target).removeEventListener(event.type, arguments.callee);
var image:DisplayObject = (event.target as LoaderInfo).content;
image.width = 50;
image.height = 50;
}
You need to get loadComplete event on your loader before playing with your MC
var myImageLoader:Loader = new Loader();
private var mcImage: MovieClip = new MovieClip();
var myImageLocation:URLRequest = new URLRequest("http://example.com/xyz.jpg");
myImageLoader.addEventListener(Event.COMPLETE, completeHandler);
myImageLoader.load(myImageLocation);
function completeHandler(e:Event){
mcImage.x = 100;
mcImage.y = 100;
mcImage.width = 50;
mcImage.height = 50;
addChild(mcImage);
mcImage.addChild(myImageLoader);
}
try this:
var myImageLoader:Loader = new Loader();
//hide until loaded
myImageLoader.visible = false;
//listen for load completed
myImageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
//...rest of your code (without setting width/height)
Then add this to resize and make visible when loaded:
function completeHandler(event:Event):void
{
myImageLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, completeHandler);
myImageLoader.content.width = 50;
myImageLoader.content.height = 50;
myImageLoader.visible = true;
}

actionscript3: reflect-class applied on rotationY

I'm using a class which applies a visual reflection-effect to defined movieclips.
I use a reflection-class from here:
link to source.
It works like a charm except when I apply a rotation to the movieclip.
In my case the reflection is still visible but only a part of it.
What am I doing wrong? How could I pass/include the rotation to the Reflection-Class ?
Thanks in advance!
This is how you apply the Reflection Class to your movieclip:
var ref_mc:MovieClip = new MoviClip();
addChild(ref_mc);
var r1:Reflect = new Reflect({mc:ref_mc, alpha:50, ratio:50,distance:0, updateTime:0,reflectionDropoff:1});
Now I apply a rotation to my movieclip:
ref_mc.rotationY = 30;
And Here the Reflect-Class:
package com.pixelfumes.reflect{
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Matrix;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.utils.setInterval;
import flash.utils.clearInterval;
public class Reflect extends MovieClip{
//Created By Ben Pritchard of Pixelfumes 2007
//Thanks to Mim, Jasper, Jason Merrill and all the others who
//have contributed to the improvement of this class
//static var for the version of this class
private static var VERSION:String = "4.0";
//reference to the movie clip we are reflecting
private var mc:MovieClip;
//the BitmapData object that will hold a visual copy of the mc
private var mcBMP:BitmapData;
//the BitmapData object that will hold the reflected image
private var reflectionBMP:Bitmap;
//the clip that will act as out gradient mask
private var gradientMask_mc:MovieClip;
//how often the reflection should update (if it is video or animated)
private var updateInt:Number;
//the size the reflection is allowed to reflect within
private var bounds:Object;
//the distance the reflection is vertically from the mc
private var distance:Number = 0;
function Reflect(args:Object){
/*the args object passes in the following variables
/we set the values of our internal vars to math the args*/
//the clip being reflected
mc = args.mc;
//the alpha level of the reflection clip
var alpha:Number = args.alpha/100;
//the ratio opaque color used in the gradient mask
var ratio:Number = args.ratio;
//update time interval
var updateTime:Number = args.updateTime;
//the distance at which the reflection visually drops off at
var reflectionDropoff:Number = args.reflectionDropoff;
//the distance the reflection starts from the bottom of the mc
var distance:Number = args.distance;
//store width and height of the clip
var mcHeight = mc.height;
var mcWidth = mc.width;
//store the bounds of the reflection
bounds = new Object();
bounds.width = mcWidth;
bounds.height = mcHeight;
//create the BitmapData that will hold a snapshot of the movie clip
mcBMP = new BitmapData(bounds.width, bounds.height, true, 0xFFFFFF);
mcBMP.draw(mc);
//create the BitmapData the will hold the reflection
reflectionBMP = new Bitmap(mcBMP);
//flip the reflection upside down
reflectionBMP.scaleY = -1;
//move the reflection to the bottom of the movie clip
reflectionBMP.y = (bounds.height*2) + distance;
//add the reflection to the movie clip's Display Stack
var reflectionBMPRef:DisplayObject = mc.addChild(reflectionBMP);
reflectionBMPRef.name = "reflectionBMP";
//add a blank movie clip to hold our gradient mask
var gradientMaskRef:DisplayObject = mc.addChild(new MovieClip());
gradientMaskRef.name = "gradientMask_mc";
//get a reference to the movie clip - cast the DisplayObject that is returned as a MovieClip
gradientMask_mc = mc.getChildByName("gradientMask_mc") as MovieClip;
//set the values for the gradient fill
var fillType:String = GradientType.LINEAR;
var colors:Array = [0xFFFFFF, 0xFFFFFF];
var alphas:Array = [alpha, 0];
var ratios:Array = [0, ratio];
var spreadMethod:String = SpreadMethod.PAD;
//create the Matrix and create the gradient box
var matr:Matrix = new Matrix();
//set the height of the Matrix used for the gradient mask
var matrixHeight:Number;
if (reflectionDropoff<=0) {
matrixHeight = bounds.height;
} else {
matrixHeight = bounds.height/reflectionDropoff;
}
matr.createGradientBox(bounds.width, matrixHeight, (90/180)*Math.PI, 0, 0);
//create the gradient fill
gradientMask_mc.graphics.beginGradientFill(fillType, colors, alphas, ratios, matr, spreadMethod);
gradientMask_mc.graphics.drawRect(0,0,bounds.width,bounds.height);
//position the mask over the reflection clip
gradientMask_mc.y = mc.getChildByName("reflectionBMP").y - mc.getChildByName("reflectionBMP").height;
//cache clip as a bitmap so that the gradient mask will function
gradientMask_mc.cacheAsBitmap = true;
mc.getChildByName("reflectionBMP").cacheAsBitmap = true;
//set the mask for the reflection as the gradient mask
mc.getChildByName("reflectionBMP").mask = gradientMask_mc;
//if we are updating the reflection for a video or animation do so here
if(updateTime > -1){
updateInt = setInterval(update, updateTime, mc);
}
}
public function setBounds(w:Number,h:Number):void{
//allows the user to set the area that the reflection is allowed
//this is useful for clips that move within themselves
bounds.width = w;
bounds.height = h;
gradientMask_mc.width = bounds.width;
redrawBMP(mc);
}
public function redrawBMP(mc:MovieClip):void {
// redraws the bitmap reflection - Mim Gamiet [2006]
mcBMP.dispose();
mcBMP = new BitmapData(bounds.width, bounds.height, true, 0xFFFFFF);
mcBMP.draw(mc);
}
private function update(mc):void {
//updates the reflection to visually match the movie clip
mcBMP = new BitmapData(bounds.width, bounds.height, true, 0xFFFFFF);
mcBMP.draw(mc);
reflectionBMP.bitmapData = mcBMP;
}
public function destroy():void{
//provides a method to remove the reflection
mc.removeChild(mc.getChildByName("reflectionBMP"));
reflectionBMP = null;
mcBMP.dispose();
clearInterval(updateInt);
mc.removeChild(mc.getChildByName("gradientMask_mc"));
}
}
}
If you have set the height and the width of your bitmapData to the same width and height of the movieclip your reflecting, you will get 'cut off'
When you rotate your movieclip, it does effectively become wider... and taller - of course at this point you've already made the bitmapData canvas area at a set width -
What you need to do it collect the real width and height of the rotating movieclip and when you redraw the bitmapData, use the new values.
I cheated when I made the same thing and just made my bitmapData 1.5 (bounds.width * 1.5) times the size of the movieclip. But thats a hack and I' a bad person for doing it.
I got it, I have to reset the bounds of the reflect Class:
myReflectClass.setBounds(newWidth,newHeight);