# wrapping dynamic text to a curve

Short and sweet, but I’ve seen it come up on a couple of projects to stump others and myself. And really, it’s not that daunting when armed with a few right triangles and the good ol’ Pythagorean theorum.

DOWNLOAD SRC

If you want to wrap a block of text to a curve, this isn’t quite the tutorial you’re looking for, though the same principles apply – you’ll have to figure out the maximum width of each line, split the copy into an array, and loop through it creating textfields and checking their textWidth to determine where the linebreaks should occur. Additionally, you might also check out gskinner’s textflowpro.

The trick is thinking of the curve as part of a circle, and then looking at the x/y location of the TextField or Object as 2 legs of a triangle whose hypotenuse is the radius of that circle.

Which means that if we know the radius to be a constant, and we know the y-location which presumably updates incrementally, then we can easily solve for the x-location using:

a

^{2}+ b^{2}= h^{2} ∴

b = √h^{2}– a^{2}
import gs.TweenLite;

var list:Array = new Array("alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "whiskey", "x-ray", "yankee", "zulu");

var curveCategories:Array = new Array();

var textForm = new TextFormat;

textForm.font = "Helvetica";

textForm.size = 10;

textForm.align = "left";

textForm.color = 0x777777;

//set init location vars

var xLoc : Number = 0;

var yLoc : Number = 15;

var yIncrement : Number = 17;

for (var i : Number = 0; i < list.length; i++) {

//create textfield

curveCategories[i] = new TextField;

curveCategories[i].htmlText = list[i];

curveCategories[i].embedFonts = true;

curveCategories[i].autoSize = "left";

curveCategories[i].setTextFormat(textForm);

//calculate x based on y and radius of circle

var r : Number = 250;

var originY : Number = 260;

var originX : Number = 20;

var legVert : Number = Math.round(Math.sqrt(Math.pow(originY – yLoc, 2)));

var legHoriz : Number = Math.round(Math.sqrt(Math.pow(r, 2) – Math.pow(legVert, 2)) + originX);

curveCategories[i].y = yLoc;

curveCategories[i].x = legHoriz;

curveCategories[i].alpha = 1;

//update y

yLoc += yIncrement;

//animate/add to stage

TweenLite.from(curveCategories[i], .4, {alpha:0, x:legHoriz+30, delay:.1 * i});

addChild(curveCategories[i]);

}

var list:Array = new Array("alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "whiskey", "x-ray", "yankee", "zulu");

var curveCategories:Array = new Array();

var textForm = new TextFormat;

textForm.font = "Helvetica";

textForm.size = 10;

textForm.align = "left";

textForm.color = 0x777777;

//set init location vars

var xLoc : Number = 0;

var yLoc : Number = 15;

var yIncrement : Number = 17;

for (var i : Number = 0; i < list.length; i++) {

//create textfield

curveCategories[i] = new TextField;

curveCategories[i].htmlText = list[i];

curveCategories[i].embedFonts = true;

curveCategories[i].autoSize = "left";

curveCategories[i].setTextFormat(textForm);

//calculate x based on y and radius of circle

var r : Number = 250;

var originY : Number = 260;

var originX : Number = 20;

var legVert : Number = Math.round(Math.sqrt(Math.pow(originY – yLoc, 2)));

var legHoriz : Number = Math.round(Math.sqrt(Math.pow(r, 2) – Math.pow(legVert, 2)) + originX);

curveCategories[i].y = yLoc;

curveCategories[i].x = legHoriz;

curveCategories[i].alpha = 1;

//update y

yLoc += yIncrement;

//animate/add to stage

TweenLite.from(curveCategories[i], .4, {alpha:0, x:legHoriz+30, delay:.1 * i});

addChild(curveCategories[i]);

}