Curved text in SVG isn't too hard, as long as you understand how to define different kinds of curved <path>
elements in SVG. When you have a curved <path>
defined in a <defs>
elements (usually just inside your root <svg>
), to make the text inside a <text>
element follow that <path>
, all that's required is to insert a <textPath>
inside the <text>
, with an xlink:href
attribute that links to the id
of the defined <path>
. The actual text for display also gets added inside the <textPath>
, like so:
<text>
<textPath xlink:href="#yourPath">
Your text
</textPath>
</text>
Unit circle, for reference:
Here, to define a path that is a partial arc of a circle I've used a combination of the M
and a
commands in the SVG path data mini-language.
m
is simply moveto
: when you start your path data with mx,y
, you're specifying the x and y coordinates where your path will start. Here we define the starting x and y coordinates with an x
of half the width (i.e., horizontal center of the SVG) minus the radius of the circle and a y
of half the height (i.e., vertical center of the SVG) in order to start the curve at (-1,0)
on the unit circle. This works of course because we centered our circle (within which we want to have our curved text fit) at exactly the horizontal and vertical center of the SVG.
a
is a general elliptical arc command.
The first two arguments are rx, ry
, the radii of the ellipse. When you're drawing a circle, as we're doing here, the radii are the same, of course, so we start our arc command with a190, 190
. (We don't want our text's baseline to sit directly on the circle in which we're drawing it, so we've taken 95% of the circle radius to use as the radius for our a
command.)
The next three arguments are the toughest to get a handle on. The first is the x-axis rotation of the ellipse. Since we're not actually drawing an ellipse, but a circle, nothing we put here will matter, so we leave it zero. The second is a boolean flag for whether to choose the longer or the shorter arc when more than one arc between the start and end points of the arc is possible, but again since we're drawing a arc, it doesn't matter what we put here; the "longer" and "shorter" arcs have the same length in the special case that an ellipse is a circle. Finally, we have the sweep-flag
argument, which controls whether the arc is drawn starting from the starting point and moving counter-clockwise (the 0
option) or clockwise (the 1
option). We're starting midway up on the left of the circle and we want to draw the lower half-circular arc, so we choose 0
to draw counter-clockwise (i.e., from 6 o'clock to 3 o'clock).
Finally we give the end coordinates of the arc. Since we're using the a
command (for relative coordinates, versus A
for absolute coordinates), our coordinate system is relative to the moveto
command we began with, and we don't have to repeat the calculations that went into calculating the moveto
coordinates. Instead we use the unit circle to reason that if our starting point was at unit (-1,0)
---now (0,0)
since it's the center of our relative universe---then we want our end point to be twice the radius for the x-coordinate because we want to move to unit (1,0)
and it takes two radius lengths to do that.
Altogether, the final elliptical arc command is a190,190 0 0 0 380,0
.
And the entire path definition d
is m485,250 a190,190 0 0 0 380,0
.
textPath
AttributesThe last couple of things to note here are two of the attributes we've defined on the <textPath>
. We use a combination of startOffset
at 50% and setting the text-anchor
to the middle
option to ensure that our text is centered on the curved path.
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js