0

I'm working on a radial menu (for a game) and I'm having some trouble with getting text along paths to behave exactly how I'd like it to. Here's an example of the menu at the moment:

Slightly Broken

I want all the text to be aligned to the center of the node it's in, and for the fontSize to be sufficiently small for the text to fit into the available space. This is achieved fairly trivially for the straight text by scalingthe font and measuring the width until it fits:

var fontSize = 19;
var titleText = new Kinetic.Text({
    text: title,
    fontSize: fontSize ,
    fontFamily: 'Calibri',
    fill: 'white',
    rotationDeg: rotation
});


while (titleText.getWidth() > availableSpace)
    titleText.setFontSize(--fontSize);

However, this approach can't be applied to the curved text because (as far as I can see) there's no way to measure how long a string is when placed along a path.

How should I achieve centering and scaling of text when it is placed along a path?

Martin
  • 12,469
  • 13
  • 64
  • 128
  • http://jsfiddle.net/ysaLp/ – Martin Jan 25 '13 at 16:12
  • Please excuse the really terrible javascript, I'm fairly new to javascript! – Martin Jan 25 '13 at 16:13
  • The function you're interested in is CreateOptionWedge, which creates 1 single wedge shape, a line of text and returns a group containing both. – Martin Jan 25 '13 at 16:18
  • the javascript is fine, and the structure is very good. First you need a function which resizes the font size depending on the width of the arc, since your arcs are all the same width, you can do something like text.length for the amount of characters and do a loop to set the font size to smaller until the width of the text path matches the width of the arc – SoluableNonagon Jan 25 '13 at 16:20
  • So perform the rescaling on a piece of linear text, and then use the font size I calculate there for the text on the path? Just tested that, it worked perfectly, thanks :D – Martin Jan 25 '13 at 16:23
  • as for centering the text, you need to do an offset calculation, which will move the text in a calculated x,y direction from its original position, since textPath doesn't have an align property – SoluableNonagon Jan 25 '13 at 16:32
  • or even simpler, add a bunch of blank spaces at the beginning of the text string (again, calculate an amount dependent on space available) – SoluableNonagon Jan 25 '13 at 16:34
  • The rescaling of a linear piece of text doesn't seem to work actually. The length of a piece of curved text seems to have no relation to the length of that text when straight. – Martin Jan 25 '13 at 16:35
  • For centering I was either thinking blank spaces at the start, or drop a few points from the start of the path. All these problems require a reliable way to measure the length of curved text though which just doesn't seem to exist :( – Martin Jan 25 '13 at 16:36
  • sorry for my comment earlier, about .length, that might not be the best thing to do, have you tried using .getTextWidth() for rescaling? the .getWidth() function just returns the width of a bounding rectangle the text is in. – SoluableNonagon Jan 25 '13 at 16:39
  • I tried getTextWidth, there seems to be no change. Straight text still works just fine, curved text is still drawn a lot wider than it looks. I might actually file this as a bug – Martin Jan 25 '13 at 16:48
  • I just ran .getTextWidth() in the jsfiddle and it returns correct values – SoluableNonagon Jan 25 '13 at 16:49
  • ok, so your wedgeWidth variable is a fixed number, and not all your wedges are of equal width (the sub-menus are of smaller width) so you have to recalculate wedgeWidth or create a different variable/size for the submenus so that they can be calculated to fit in there – SoluableNonagon Jan 25 '13 at 16:57
  • Ah wedgeWidth is used to define the distance from the inner radius to the outer radius of a wedge, _not_ the angle around the wedge! – Martin Jan 25 '13 at 16:58
  • http://jsfiddle.net/ysaLp/4/ try this one out – SoluableNonagon Jan 25 '13 at 17:03
  • so you pretty much have to calculate the length of the arc at the midpoint of the wedge and resize the font until it fits inside the arc – SoluableNonagon Jan 25 '13 at 17:04
  • I've tried calculating the arc length, that doesn't work. the "circumference" variable just above where the text objects are created is the length of the arc. However the circumference is much much larger than the supposed width of text which can fit into the same space. – Martin Jan 25 '13 at 17:07
  • post your code for the calculation of the arc? – SoluableNonagon Jan 25 '13 at 17:08
  • nvm it's the circumference var? – SoluableNonagon Jan 25 '13 at 17:08
  • Yep, circumference is the length of the arc through the center of the wedge – Martin Jan 25 '13 at 17:10
  • http://jsfiddle.net/ysaLp/5/ well, take a look at the resizing loop, this gets you a lot closer. – SoluableNonagon Jan 25 '13 at 17:13
  • http://jsfiddle.net/ysaLp/6/ also, try your starting font size at 15, rather than 19 – SoluableNonagon Jan 25 '13 at 17:20
  • It looks like with a fontSize of 15 the loop doesn't actually resize any text - it just happens that 15 is small enough for stuff to fit in without needing any resizing! – Martin Jan 25 '13 at 17:27
  • you're right, sorry, seems I'm not much help anymore, I had the same problem of trying to resize text to fit in a rectangle. Maybe this points you in the right direction: http://stackoverflow.com/questions/687998/auto-size-dynamic-text-to-fill-fixed-size-container – SoluableNonagon Jan 25 '13 at 17:37
  • also, maybe try starting from a very small font and work your way up, instead of big to small – SoluableNonagon Jan 25 '13 at 17:39
  • I've realized the font size has to be set before you calculate the path data otherwise it will always be off – SoluableNonagon Jan 25 '13 at 17:57

1 Answers1

1

Here is a hack in terms of centering, but you get the idea:

http://jsfiddle.net/ysaLp/2/

basically when you have each item in your list, you want to add blank spaces to the beginning, dependent on total space in the arc.

you can do (again, inside a loop):

textPathObjectName.setText(' ' + textPathObjectName.getText()); //dependent on the length of the width of text ( .getTextWidth() )

In terms of resizing you get : http://jsfiddle.net/ysaLp/5/

    for (var i = 1; i < 5 && titleText.getTextWidth() > circumference ; i++)
        titleText.setFontSize(titleText.getFontSize()-i);

which lowers your font until it "fits" into your wedge's circumference

It also helps to start your font at a lower value, since you are calculating the path data right after, set the font size at 15 first.

SoluableNonagon
  • 11,541
  • 11
  • 53
  • 98