author: Krasimir Tsonev

Hi there, I'm . Senior front-end engineer with over 13 years of experience. I write, speak and occasionally code stuff. Follow me on Twitter, GitHub, Facebook or LinkedIn

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.
If you enjoy this post, share it on Twitter, Facebook or LinkedIn. Or maybe comment below: