给定一个圆心为(200,200),半径为25的圆,如何画出一条从270度到135度的弧以及一条从270度到45度的弧?
0度表示它在x轴上(右侧)(表示它是3点钟位置) 270度表示12点钟位置,90度表示6点钟位置
更一般地说,弧的路径是圆的一部分
x, y, r, d1, d2, direction
意义
center (x,y), radius r, degree_start, degree_end, direction
给定一个圆心为(200,200),半径为25的圆,如何画出一条从270度到135度的弧以及一条从270度到45度的弧?
0度表示它在x轴上(右侧)(表示它是3点钟位置) 270度表示12点钟位置,90度表示6点钟位置
更一般地说,弧的路径是圆的一部分
x, y, r, d1, d2, direction
意义
center (x,y), radius r, degree_start, degree_end, direction
当前回答
ES6版本:
const angleInRadians = angleInDegrees => (angleInDegrees - 90) * (Math.PI / 180.0);
const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
const a = angleInRadians(angleInDegrees);
return {
x: centerX + (radius * Math.cos(a)),
y: centerY + (radius * Math.sin(a)),
};
};
const arc = (x, y, radius, startAngle, endAngle) => {
const fullCircle = endAngle - startAngle === 360;
const start = polarToCartesian(x, y, radius, endAngle - 0.01);
const end = polarToCartesian(x, y, radius, startAngle);
const arcSweep = endAngle - startAngle <= 180 ? '0' : '1';
const d = [
'M', start.x, start.y,
'A', radius, radius, 0, arcSweep, 0, end.x, end.y,
fullCircle ? 'Z':''
].join(' ');
return d;
};
其他回答
我会使用其他答案的代码,它们看起来都是互相复制的,但是我会让起点是开始角度的函数而终点是结束角度的函数。
我将使用绝对值使大圆弧标志与顺序无关,并通过360度模数使角度与数值大小无关。
var start = polarToCartesian(x, y, radius, startAngle);
var end = polarToCartesian(x, y, radius, endAngle);
largeArcFlag = Math.abs((endAngle - startAngle) % 360) <= 180 ? "0" : "1";
clockwiseFlag = (endAngle > startAngle) ? "1" : "0";
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, largeArcFlag, clockwiseFlag, end.x, end.y
].join(" ");
向威利道歉;我还没读到最后,他也发现了同样的事情。如果你喜欢我的帖子,就给他投票吧!
ES6版本:
const angleInRadians = angleInDegrees => (angleInDegrees - 90) * (Math.PI / 180.0);
const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
const a = angleInRadians(angleInDegrees);
return {
x: centerX + (radius * Math.cos(a)),
y: centerY + (radius * Math.sin(a)),
};
};
const arc = (x, y, radius, startAngle, endAngle) => {
const fullCircle = endAngle - startAngle === 360;
const start = polarToCartesian(x, y, radius, endAngle - 0.01);
const end = polarToCartesian(x, y, radius, startAngle);
const arcSweep = endAngle - startAngle <= 180 ? '0' : '1';
const d = [
'M', start.x, start.y,
'A', radius, radius, 0, arcSweep, 0, end.x, end.y,
fullCircle ? 'Z':''
].join(' ');
return d;
};
对于寻求答案的人(我也是),如果不是必须使用arc,绘制部分圆的一个更简单的解决方案是使用SVG的stroke-dasharray <circle>。
将虚线数组分为两个元素,并将其范围缩放到所需的角度。起始角度可以使用冲程-达霍夫集进行调整。
看不见一个余弦。
完整的例子和解释: https://codepen.io/mjurczyk/pen/wvBKOvP
这是一个老问题,但我发现代码很有用,节省了我三分钟的思考:)所以我在@opsb的答案中添加了一个小扩展。
如果你想把这个弧转换成一个切片(允许填充),我们可以稍微修改代码:
function describeArc(x, y, radius, spread, startAngle, endAngle){ var innerStart = polarToCartesian(x, y, radius, endAngle); var innerEnd = polarToCartesian(x, y, radius, startAngle); var outerStart = polarToCartesian(x, y, radius + spread, endAngle); var outerEnd = polarToCartesian(x, y, radius + spread, startAngle); var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1"; var d = [ "M", outerStart.x, outerStart.y, "A", radius + spread, radius + spread, 0, largeArcFlag, 0, outerEnd.x, outerEnd.y, "L", innerEnd.x, innerEnd.y, "A", radius, radius, 0, largeArcFlag, 1, innerStart.x, innerStart.y, "L", outerStart.x, outerStart.y, "Z" ].join(" "); return d; } 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)) }; } var path = describeArc(150, 150, 50, 30, 0, 50) document.getElementById("p").innerHTML = path document.getElementById("path").setAttribute('d',path) <p id="p"> </p> <svg width="300" height="300" style="border:1px gray solid"> <path id="path" fill="blue" stroke="cyan"></path> </svg>
好了!
由wdebeaum得到的原始极坐标笛卡尔函数是正确的:
var angleInRadians = angleInDegrees * Math.PI / 180.0;
使用以下方法反转起始点和结束点:
var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);
(对我来说)是混乱的,因为这将反转扫旗。使用:
var start = polarToCartesian(x, y, radius, startAngle);
var end = polarToCartesian(x, y, radius, endAngle);
使用sweep-flag = "0"绘制"正常"逆时针弧线, 我认为这更直接。 参见https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths