W3C home > Mailing lists > Public > www-svg@w3.org > September 2010

How to position bounding box of rotated text?

From: Dr. Olaf Hoffmann <Dr.O.Hoffmann@gmx.de>
Date: Thu, 9 Sep 2010 17:52:17 +0200
To: www-svg@w3.org, jan-felix.schwarz@student.hpi.uni-potsdam.de
Message-Id: <201009091752.17778.Dr.O.Hoffmann@gmx.de>
Jan-Felix Schwarz:

>Hello,
>
>I am mailing to the list because I struggle to position a rotated text 
>element in the desired manner. I want to achieve the following:

Maybe not the the optimal mailing list, if you do not want to suggest to 
simplify this ... 

> - A text element shall be rotated by `a` degree.

Around which point? 
Lets assume the origin 0 and the text at position T
in the current coordinate sytem.
With a rotation matrix D(a) you will get the position
of the text in the old coordinate system as 
T' = D(a)T

See http://www.w3.org/TR/SVG11/coords.html

> - The resulting (imaginary) bounding box of the rotated text shall be 
>translated, so that its upper left is at position `x,y`.

Obviously you need a translation of -T' + (x,y) if you mean
upper left in the current coordinate system.
Better you use (0,0) for T right from the start to get it
simpler.

Typically this is only the lower left corner of the text.
If you know the size of the font f precisely you can use
an additional shift for T about (0,f). But it is maybe
simpler to use baseline-shift of -100%.

> - I don't know the content, i.e., the width, of the text element beforehand.

This is not really important, because the initial value of text-anchor is
start, this is already the left side in the current coordinate system
typically.

But if f you mean above the upper left in the old coordinate system, 
you have to distinguish between different angles a.
For angles between 0 and 90 degree the method is ok.
Between 90 and 180 degree you need no additional shift.
For angles between 180 and 360 degree you better use text-anchor="end"
and the shift for 180 to 270 degree and no shift for 270 to 360 degree
and so on for smaller or larger angles.

>How can I achieve that without any post-processing like JavaScript in the 
>browser? Is it possible to wrap the text element with some other element 
>which makes up a bounding box and can be absolutely positioned?
>
>Hoping some of you experts can lead me on the right track here. Thanks in 
>advance!

Something like this might work (because text has no x and y attribute, it is 
already rotated around the text position - and the g element is used only
to simplify the option to add some more text):

<circle cx="500" cy="400" r="5" fill="red" />
<g xml:lang="de" text-anchor="start"
    font-size="20" font-family="sans-serif"
    transform="translate(500,400)">
<text transform="rotate(60)"><tspan baseline-shift="-100%">Irgendein 
Text</tspan></text>
<text transform="rotate(60) translate(0,20)" stroke="blue"
fill="none">Irgendein Text</text>
</g>

Note, that the glyphs are typically smaller than the font-size, this 
can cause some undesired additional offset. To get this under 
control, one can provide an embedded font using the font element
in SVG 1.1 (full) or SVG tiny 1.2.

If you need a box with text in it inlcuding automatic or manual line breaks,
you can use textArea from SVG tiny 1.2: 
http://www.w3.org/TR/SVGMobile12/text.html#TextInAnArea
(note the SVG tiny 1.2 is typically not implemented in older viewers or
older versions of viewers).

But for this indeed the situation gets simpler even for more complex text
including line breaks:
<g xml:lang="de"
    font-size="20" font-family="sans-serif">
<textArea transform="translate(500,400) rotate(60)" 
 width="400">Irgendein Text<tbreak/>und noch mehr</textArea>
</g>

However with manual line breaks you can do almost the same
in SVG 1.1 with a tspan for each line within the text element and
using the y attribute of tspan to get a vertical shift for each line in
the current coordinate system.
<g xml:lang="de" text-anchor="start"
    font-size="20" font-family="sans-serif">
<text transform="translate(500,400) rotate(60)" stroke="magenta" fill="none">
<tspan x="0" y="20">Irgendein Text</tspan>
<tspan x="0" y="45">und noch mehr</tspan>
</text>
</g>

As you can see, there are several ways to get the intended result without
much own calculation - basically you have to nest elements or to put the
transformations in the right order.
Is this what you need or did I misunderstand something?

Olaf
Received on Thursday, 9 September 2010 16:02:43 GMT

This archive was generated by hypermail 2.3.1 : Friday, 8 March 2013 15:54:46 GMT