Change Text Size and Keep Text Vertically Centered - actionscript-3

How can I change the textSize of a dynamic text field and keep the text resting on the baseline? When I call this function and it affects the size of the text, the text gradually rises upwards within the text field as the text size decreases.
function autoFormatSize(myTextField)
{
if (! textFormat && ! textSize)
{
var textFormat:TextFormat = new TextFormat();
var textSize:int = new int();
}
textFormat.size = 50;
textSize = 50;
for (var i=0; myTextField.textWidth>myTextField.width-10; i++)
{
textSize--;
textFormat.size = textSize;
myTextField.setTextFormat(textFormat);
}
}
UPDATE
Here's a visual illustration of what I'm trying to do:

Use textHeight to get the height of the text. Here is how you'd position a textfield over an mc of a line:
var tfMain: TextFormat = new TextFormat();
tfMain.size = 100;
tMain.setTextFormat(tfMain);
trace(tMain.textHeight);
tMain.y = Math.ceil(mcUnderline.y - tMain.textHeight);
Use ceil to make sure it's on the x.

Create a Sprite and added it to stage, then align your TexField based on the Sprite. As coded below
with(bg.graphics) {
clear();
beginFill(0xeeeeee, 1);
lineStyle(1, 0x999999);
drawRect(0, 0, 200, 30);
endFill();
}
txt.x = bg.x + bg.width/2 - txt.width/2;
txt.y = bg.y + bg.height/2 - txt.height/2;

Considering your comment, have you thought about using autoSize instead? Something like:
var tf:TextField = yourTextField; //on timeline
tf.autoSize = TextFieldAutoSize.LEFT;
var textFormat:TextFormat = new TextFormat();
textFormat.size = 14;
var oldY:Number = tf.y + tf.height;
tf.setTextFormat(textFormat);
tf.y = oldY - tf.height;

To adjust your text to your text field, you have to consider a 2px gutter for each side of the text, so your function can be like this :
function autoFormatSize(myTextField)
{
var gutter:int = 2 * 2; // 4px
var textSize:int = 50;
var textFormat:TextFormat = new TextFormat();
textFormat.size = textSize;
for (var i:int = 0; myTextField.textWidth > myTextField.width - gutter; i++)
{
textSize --;
textFormat.size = textSize;
myTextField.setTextFormat(textFormat);
}
myTextField.height = myTextField.textHeight + gutter;
}
Hope that can help.

Related

My bar charts overlap eachother. Need help to solve it

im making a code where I have an input field and a button on my screen. In the code below btnLeggTil (its norwegian) adds the number you wrote in the input field. It determines the height of the bars. My code is supposed to let the user add bars of whatever the height he/she prefers. As you can see I have put alot of my code inside a loop. The problem with the code is that the bars it makes, overlap eachother. I need to have a space between each bar, but don't know how. Thanks in advance! You can test out the code yourself and see (just remember to make a button and input field with names btnLeggTil and txtInn.
("høyde" means height) ("bredde" means width) ("verdier" means values) sorry its all norwegian
var verdier:Array = new Array();
btnLeggTil.addEventListener(MouseEvent.CLICK, leggtil);
function leggtil (evt:MouseEvent)
{
verdier.push(txtInn.text);
var totHøyde:int = 200; //total height on diagram
var totBredde:int = 450; //total width on diagram
var antall:int = verdier.length;
var xv:int = 50;
var yb:int = 350;
var bredde:int = (totBredde/antall) * 0.8;
var mellom:int = (totBredde/antall) * 0.2;
var maksHøyde:int = maksVerdi(verdier);
function maksVerdi(arr:Array):Number //finds the biggest value in the array
{
//copies to not destroy the order in the original
var arrKopi:Array = arr.slice();
arrKopi.sort(Array.NUMERIC|Array.DESCENDING);
return arrKopi[0];
}
for(var i:int = 0; i < verdier.length; i++)
{
graphics.lineStyle(2, 0x000000);
graphics.beginFill(0x00ff00);
graphics.drawRect(xv + (bredde+mellom)*i, yb, bredde, -verdier[i] * (totHøyde/maksHøyde));
graphics.endFill();
var txtTall = new TextField();
txtTall.x = xv + (bredde+mellom)*i + 5;
txtTall.y = yb - verdier[i] - 10;
txtTall.type = "dynamic";
txtTall.text = verdier[i];
addChild(txtTall);
}
}
You need to modify your for loop a bit,
graphics.clear();
graphics.lineStyle(2, 0x000000);
graphics.beginFill(0x00ff00);
for(var i:int = 0; i < verdier.length; i++)
{
graphics.drawRect(xv + (bredde+mellom)*i, yb, bredde, -verdier[i] * (totHøyde/maksHøyde));
var txtTall = new TextField();
txtTall.x = xv + (bredde+mellom)*i + 5;
txtTall.y = yb - verdier[i] - 10;
txtTall.type = "dynamic";
txtTall.text = verdier[i];
addChild(txtTall);
}
graphics.endFill();

myTextField.text does not return any value

I'm trying to make a numberline with boxes pointing at different values. Inside each box is a TextField where the user is supposed to wright down the value the box is pointing at. When all the boxes are filled out, the answere in the boxes should be compared to the correct answeres.
The problem is that when I try to acsess the text in the textField, 1-2 of them randomly won't return any values. The TextFields that don't respond are also impossible to edit and navigate inside after a number is filled out.
This is the code where I construct the textField:
var textFields:Array = [];
var box:Sprite = new Sprite();
var tfor:TextFormat = new TextFormat();
for (var i:int = 0; i<3; i++)
{
tfor.size = 30;
var tfb:TextField = new TextField();
tfb.defaultTextFormat = tfor;
tfb.width = boxWidth;
tfb.height = boxWidth;
tfb.maxChars = 3;
tfb.text = "";
tfb.restrict = "0-9.";
tfb.multiline = false;
tfb.x = bx;
tfb.y = by;
tfb.selectable = true;
tfb.type = TextFieldType.INPUT;
box.addChild(tfb);
textFields.push(tfb);
}
And this is where I check the answere:
public function checkBoxAnswere(numbs:Array) {
var points:Number = 0;
for(var i:int = 0; i<textFields.length; i++) {
trace("numb:"+numbs[i]+"arrowText "+textFields[i].text+" .");
//begDes is a function whitch round a value mutch like the .toFixed(number) but returns a number insted of a string
if(begDes(numbs[i], 2)==begDes(Number(textFields[i].text), 2)) {
points+= 0.5;
}
}
return points;
}
It is the textField.text that wont be read. There is no error massenges.

Combobox's dropdown position for ipad (retina display) using As3 air application

the application which i created for ipad retina display in as3 mobile application. the combobox displayed in the screen in very small in size due to that changed the font, and size of the combo box dynamically. which all almost work fine. but the problem which was faced on the positioning of dropdown list, could not able to change the y position.
var tf:TextFormat = new TextFormat();
tf.font = "Arial";
tf.size = 35;
tf.color = 0x747070;
var dp:DataProvider = new DataProvider();
dp.addItem({label:"London", data:"item1"});
dp.addItem({label:"Paris", data:"item2"});
dp.addItem({label:"Sofia", data:"item3"});
dp.addItem({label:"Praha", data:"item4"});
dp.addItem({label:"Praha1", data:"item5"});
dp.addItem({label:"Praha2", data:"item6"});
_clip = new ComboBoxClip();
_clip.combo.dataProvider = dp;
_clip.combo.width = 199;
_clip.combo.height = 50;
_clip.combo.textField.setStyle("embedFonts", true);
_clip.combo.textField.setStyle("textFormat", tf);
_clip.combo.textField.setStyle("textPadding", 5);
_clip.combo.dropdown.setStyle("cellRenderer", CustomCellRenderer);
_clip.combo.dropdown.rowHeight = 31;
_clip.combo.dropdown.setStyle("paddingTop", 150);
_clip.combo.addEventListener(Event.CHANGE, onComboChange);
_clip.combo.tabIndex = 1;
_clip.x = _clip.y = 30;
addChild(_clip);
And the CustomeCellRenderer Class
public class CustomCellRenderer extends CellRenderer {
public function CustomCellRenderer() {
super();
var tf:TextFormat = new TextFormat();
tf.font = "Arial";
tf.size = 35;
tf.color = 0x747070;
setStyle("embedFonts", true);
setStyle("textFormat", tf);
}
override protected function drawLayout():void {
super.drawLayout()
textField.y += 2;
textField.x += 4;
}
}
Change the comboBox & dropdown height, width and text size to meet your needs.
var dp:DataProvider = new DataProvider();
dp.addItem({label:"London", data:"item1"});
dp.addItem({label:"Paris", data:"item2"});
dp.addItem({label:"Sofia", data:"item3"});
dp.addItem({label:"Praha", data:"item4"});
dp.addItem({label:"Praha1", data:"item5"});
dp.addItem({label:"Praha2", data:"item6"});
var tf:TextFormat;
tf = new TextFormat("Arial", 22, 0x747070);
comboBox.textField.height = 22;
comboBox.textField.setStyle("textFormat", tf);
comboBox.dropdown.setRendererStyle("textFormat", tf);
comboBox.dropdown.rowHeight = 32; //height of dropdown row
comboBox.dropdownWidth = 199; //combox and dropdown same width
comboBox.width = 199; //combox and dropdown same width
comboBox.height = 36;
comboBox.move(100, 100); //(x,y) use this to position comboBox
comboBox.prompt = "Select Something"; //if you need a prompt
comboBox.selectedItem = comboBox.getItemAt(-1); //show prompt
comboBox.dataProvider = dp;
comboBox.addEventListener(Event.CHANGE, onComboChange);
addChild(comboBox);

Positioning of Dynamically attached library objects in ActionScript 3.0

I am re-learning ActionScript, and I am trying to learn from
digitaldogbyte.com 'Dynamically attached library objects in ActionScript 3.0'. This example, in digialdogbyte, sets the position of each MovieClip across the X position. At high number of numberOfClips, the Objects run right and of the Stage, and out-of-view.
I am trying to adapt the following script to:
wrap the flow of objects to a new line when the edge of the Stage is reached
every other block is coloured red with text colour set to white
The ActionScript:
var numberOfClips:Number = 150;
var xStart:Number = 0;
var yStart:Number = 0;
var xVal:Number = xStart;
var xOffset:Number = 2;
for (var i:Number=0; i<numberOfClips; i++)
{
var mc:myClip = new myClip();
mc.name = "myClip"+(i+1);
this.addChild (mc);
mc.y = yStart;
mc.x = xVal;
xVal = mc.x + mc.width + this.xOffset;
mc.label_txt.text = (i).toString();
}
I'd be grateful if anyone could suggest ways to adapt this script as such.
Add something simple like:
var numberOfClips:Number = 150;
var grid:Rectangle = new Rectangle(0, 0, 20, 20);
for(var i:Number = 0; i < numberOfClips; i++)
{
var mc:myClip = new myClip();
addChild(mc);
mc.x = grid.x;
mc.y = grid.y;
grid.x += grid.width;
// If the new x position is outside of the stage, reset it and
// increase the y position.
if(grid.x + grid.width > stage.stageWidth)
{
grid.x = 0;
grid.y += grid.height;
}
}
You can adjust the width and height of the grid on line 2.

AS3 proportionally scaling external image

Currently I am using a for loop to dynamically load XML images and place them in a grid as thumbnails. I have the arrangement set and all the data is loading smoothly, but now I need to make the images scale to small 100px x 100px thumbs in small container movieclips. My code is as follows.
import gs.*;
import gs.easing.*;
var bttnHeight:Number = 20;
var select:Number = 0;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, showXML);
xmlLoader.load(new URLRequest("testxml.xml"));
var list_mc:Array = new Array();
function showXML(e:Event):void {
XML.ignoreWhitespace = true;
var nodes:XML = new XML(e.target.data);
var gallcount = nodes.gallery.length();
var list_mc = new listitem();
//Generate menu to select gallery
function populateMenu():void {
var spacing:Number = 0;
for (var i=0; i<gallcount; i++) {
list_mc[i] = new listitem();
list_mc[i].name = "li" + i;
list_mc[i].y = i*bttnHeight;
list_mc[i].gallname.text = nodes.gallery[i].attributes();
menu_mc.addChild(list_mc[i]);
list_mc[i].addEventListener(MouseEvent.ROLL_OVER, rollover);
list_mc[i].addEventListener(MouseEvent.ROLL_OUT, rollout);
list_mc[i].buttonMode = true;
list_mc[i].mouseChildren = false;
}
menu_mc.mask = mask_mc;
}
//list_mc.mask(mask_mc);
var boundryWidth = mask_mc.width;
var boundryHeight = mask_mc.height;
var diff:Number = 0;
var destY:Number = 0;
var ratio:Number = 0;
var buffer:Number = bttnHeight*2;
function findDest(e:MouseEvent):void {
if (mouseX>0 && mouseX<(boundryWidth)) {
if (mouseY >0 && mouseY<(boundryHeight)) {
ratio = mouseY/boundryHeight;
diff = menu_mc.height-boundryHeight+buffer;
destY = Math.floor(-ratio*diff)+buffer/2;
}
}
}
var tween:Number = 5;
//This creats the scroll easing
function moveMenu() {
if (menu_mc.height>boundryHeight) {
menu_mc.y += (destY-menu_mc.y)/tween;
if (menu_mc.y>0) {
menu_mc.y = 0;
} else if (menu_mc.y<(boundryHeight-menu_mc.height)) {
menu_mc.y = boundryHeight-menu_mc.height;
}
}
}
function rollover(e:Event):void {
TweenLite.to(e.currentTarget.li_bg, .4, {tint:0x334499});
}
function rollout(e:Event):void {
TweenLite.to(e.currentTarget.li_bg, .4, {removeTint:true});
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, findDest);
stage.addEventListener(Event.ENTER_FRAME, moveMenu);
populateMenu();
select = 0;
//Generate thumbnails
function genThumb():void {
var photos = nodes.gallery[select].photo;
var thumbframe:Array = new Array();
var row = 0;
var column = 0;
var loaderArray:Array = new Array();
for (var i=0; i<photos.length(); i++) {
thumbframe[i] = new Sprite;
thumbframe[i].graphics.beginFill(0x0000FF);
thumbframe[i].graphics.drawRect(0,0,100,100);
thumbframe[i].graphics.endFill();
thumbframe[i].y = row;
thumbframe[i].x = column;
loaderArray[i] = new Loader();
loaderArray[i].load(new URLRequest(photos[i].text()));
trace(loaderArray[i].height);
var index = i+1;
container_mc.addChild(thumbframe[i]);
if (index%5 == 0) {
row=row+120;
column = 0;
} else {
column=column+120;
}
thumbframe[i].addChild(loaderArray[i]);
}
}
genThumb();
}
Both the loaders and the containers are in respective arrays. The images load correctly, but I am at a loss for how to scale them (ultimately I'd like to integrate a tween to animate as they load as well if possible.)
Thanks in advance for any aid!
You look like you need to scale your bitmaps into a 100x100 square. You'll need to wait until the loader has completed loading to do that because until then you won't know what the dimensions of the item are.
When you create your loader, add an event listener, like this:
loaderArray[i].contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
and then add this function:
function onLoadComplete(event:Event):void
{
var info:LoaderInfo = LoaderInfo(event.currentTarget);
info.removeEventListener(Event.COMPLETE);
var loader:Loader = info.loader;
var scaleWidth:Number = 100 / loader.width;
var scaleHeight:Number = 100 / loader.height;
if (scaleWidth < scaleHeight)
loader.scaleX = loader.scaleY = scaleWidth;
else
loader.scaleX = loader.scaleY = scaleHeight;
}
This may be a bit complicated, but all it really does is clean up the event listener that you had added, and find the dimensions of the loader (which it can get now because it's finished loading), and scale the loader appropriately.
If you need it to be centered within your thumbnail, add this to the bottom of the onLoadComplete method:
loader.x = (100 - loader.width) * 0.5;
loader.y = (100 - loader.height) * 0.5;
or you need it to take up the whole thumbnail and cut off the edges, change it to this (the inequality is the other-way around)
if (scaleWidth > scaleHeight)
loader.scaleX = loader.scaleY = scaleWidth;
else
loader.scaleX = loader.scaleY = scaleHeight;
and add this:
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
g.beginFill(0x00FF00);
g.drawRect(0, 0, 100, 100);
g.endFill();
loader.mask = g;
I haven't tested this, so there may be a few glitches, but hopefully it gives you the right idea.