I'm using this piece of code to draw arcs and so far it's been great, however I've encountered an issue with textPath
that I cannot figure out.
Please run the following snippet.
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function describeArc(x, y, radius, startAngle, endAngle){
var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);
var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
].join(" ");
return d;
}
var correctPath = document.getElementById('correctPath'),
incorrectPath = document.getElementById('incorrectPath'),
expectedPath = document.getElementById('expectedPath');
correctPath.setAttribute('d', describeArc(24,24,20,0,90));
incorrectPath.setAttribute('d', describeArc(24,24,20,90,0));
expectedPath.setAttribute('d', 'M24 2.75 a 1 1 1 1 1 0 42.8');
.col {width: 32%; float: left; padding: 0.5%}
<div class="col">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<defs>
<path d="" id="correctPath"></path>
</defs>
<circle r="24" cx="24" cy="24" fill="#eee"></circle>
<text id="nameText" fill="green" font-size="3.2">
<textPath xlink:href="#correctPath">correct</textPath>
</text>
</svg>
</div>
<div class="col">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<defs>
<path d="" id="incorrectPath"></path>
</defs>
<circle r="24" cx="24" cy="24" fill="#eee"></circle>
<text id="nameText" fill="red" font-size="3.2">
<textPath xlink:href="#incorrectPath">incorrect</textPath>
</text>
</svg>
</div>
<div class="col">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<defs>
<path d="" id="expectedPath"></path>
</defs>
<circle r="24" cx="24" cy="24" fill="#eee"></circle>
<text id="nameText" fill="blue" font-size="3.2">
<textPath xlink:href="#expectedPath">expected</textPath>
</text>
</svg>
</div>
So using
correctPath.setAttribute('d', describeArc(24,24,20,0,90));
it seems to do the thing that is supposed to do, but in this case I would need to turn the text upside down so I'm trying to reverse startAngle
with endAngle
incorrectPath.setAttribute('d', describeArc(24,24,20,90,0));
and you see the result which is incorrect, it basically relocates the arc center coordinates to another position, instead of giving me the coordinates that I was expecting.
How can I adjust these two functions to be able to handle the reverse of the startAngle
and endAngle
to produce the expected outcome?
The arc command is structered like this:
The last flag,
sweep-flag
, describes the direction an arc goes around a circle. If you swap the start angle and end angle in polar coordinates, you also swap the direction: endAngle > startAngle means clockwise, startAngle > endAngle counterclockwise. Your function draws the arc from endAngle to startAngle, so the reverse applies.A simple solution would be to implement this rule:
But note that this rule will fail as soon as you want to really go past the end of the circle in degrees. Lets say, from 300 degrees to 90 degrees clockwise. If that is your intention, you must state it explicitely and pass the rotation direction as a parameter to your function.
(Your reference path
M24 2.75 a 1 1 1 1 1 0 42.8
is impossible to draw and automatically rewritten asM 24,2.75 a 21.4,21.4 1 1 1 0 42.8
. See these notes for the rules governing this substitution.)