AS3: dynamic text field to curve (TextField on an arcing path)
[2]Most of the articles here are tightly connected to my daily work. As you probably know from one of my latest posts (runtime font loading/embedding) I worked a lot with texts these days. There was a request for producing curved text from a dynamic field. Of course it wasn't so easy to create such a feature. I wrote a simple class that did the job and I decided to share it.
We all know that it is not possible to transform a TextField object to a curve directly. What we can do is to create as many TextField objects as the letters that we have and set their position and rotation. Also it is very important to embed the font that you are going to use. Otherwise the script will not be able to set the correct x, y and rotation.
1. The CurvedText constructor
public
function CurvedText(text: String, radius: Number = 200, startAngle: Number = 0, endAngle: Number = 360, direction: String = "up", textFormat: TextFormat = null) {
_text = text;
_radius = radius;
_startAngle = startAngle;
_endAngle = endAngle;
_direction = direction;
_textFormat = textFormat;
_letters = [];
_totalAngle = Math.abs(_startAngle) + Math.abs(_endAngle);
}
- text - the text that will be displayed- radius - the radius of the circle- startAngle - the angle where the text will start from- endAngle - the angle where the text will stop- direction - CurvedText.DIRECTION_UP or CurvedText.DIRECTION_DOWN- textFormat - the TextFormat object which will be used (you should at least set the font property at least)For better understanding of the start and end angle please check the following diagram:[1]
2. Creating the text fields
var numOfLetters: int = _text.length;
for (var i: int = 0; i & lt; numOfLetters; i++) {
var letter: Object = getLetterObject(_text.charAt(i));
letter.stepDegrees = _totalAngle / numOfLetters;
_letters.push(letter);
_widthOfText += letter.fieldWidth;
_letterHolder.addChild(letter.movie);
}..private
function getLetterObject(letter: String): Object {
// setting default text format
if (!_textFormat) {
_textFormat = new TextFormat();
_textFormat.align = TextFormatAlign.CENTER;
_textFormat.font = "Verdana";
_textFormat.size = 12;
_textFormat.color = 0x000000;
}
// creating the field
var movie: MovieClip = new MovieClip();
var field: TextField = new TextField();
field.width = 10;
field.defaultTextFormat = _textFormat;
field.embedFonts = true;
field.multiline = false;
field.autoSize = TextFieldAutoSize.CENTER;
field.text = letter;
field.x = -field.width / 2;
field.y = -field.height / 2;
if (showLetterBorder) {
field.border = true;
}
movie.addChild(field);
return {
movie: movie,
field: field,
fieldWidth: field.width,
fieldHeight: field.height
};
}
Nothing special actually. Simply creating a new TextField object for every letter.
3. Positioning the fields
var numOfLetters: int = _letters.length;
var degrees: Number = _startAngle;
for (var i: int = 0; i & lt; numOfLetters; i++) {
var angle: Number = _letters[i].stepDegrees + degrees;
if (_direction == DIRECTION_DOWN) {
angle -= 180;
_letters[i].movie.scaleY = -1;
} else {
xValue = _radius * Math.cos((angle - 90) / 180 * Math.PI);
yValue = _radius * Math.sin((angle - 90) / 180 * Math.PI);
}
var xValue: int = _radius * Math.cos((angle - 90) / 180 * Math.PI);
var yValue: int = _radius * Math.sin((angle - 90) / 180 * Math.PI);
_letters[i].movie.x = xValue;
_letters[i].movie.y = yValue;
_letters[i].movie.rotation = angle;
degrees += _letters[i].stepDegrees;
}
4. The usage of the class
var tf: TextFormat = new TextFormat();
tf.font = "Verdana";
tf.size = 15;
tf.color = 0x000000;
var radius: Number = 100;
var startAngle: Number = -60;
var endAngle: Number = 60;
var direction: String = CurvedText.DIRECTION_UP;
var text: CurvedText = new CurvedText("text here", radius, startAngle, endAngle, direction, tf);
text.showCurve = true;
text.showLetterBorder = true;
text.draw();
addChild(text);
P.S.If you play for a while with the example above you will see that some of the letters are not positioned very well. It is because they have different width than the others. So the script needs a little bit more work to be a perfect one.