Javascript SVG圆环切片作为路径元素(环形扇区)

Javascript SVG圆环切片作为路径元素(环形扇区),javascript,svg,Javascript,Svg,当然,这不是一个错误,但我对如何通过贝塞尔曲线在点之间获得一个完美的圆弧感到困惑 我需要这样的形状: x1 = centerPointX+outerRadius*Math.cos(currentAngle) y1 = centerPointY+outerRadius*Math.sin(currentAngle) x2 = centerPointX+innerRadius*Math.cos(currentAngle) y2 = centerPointY+innerRadius*Math.sin(c

当然,这不是一个错误,但我对如何通过贝塞尔曲线在点之间获得一个完美的圆弧感到困惑

我需要这样的形状:

x1 = centerPointX+outerRadius*Math.cos(currentAngle)
y1 = centerPointY+outerRadius*Math.sin(currentAngle)
x2 = centerPointX+innerRadius*Math.cos(currentAngle)
y2 = centerPointY+innerRadius*Math.sin(currentAngle)
x3 = centerPointX+outerRadius*Math.cos(currentAngle2)
y3 = centerPointY+outerRadius*Math.sin(currentAngle2)
x4 = centerPointX+innerRadius*Math.cos(currentAngle2)
y4 = centerPointY+innerRadius*Math.sin(currentAngle2)

所以我一直在用下面的公式从中心点,半径和角度计算四个角点:(x?,y?=(x+d cosα,y+d sinα),在我的咖啡脚本中看起来像这样:

x1 = centerPointX+outerRadius*Math.cos(currentAngle)
y1 = centerPointY+outerRadius*Math.sin(currentAngle)
x2 = centerPointX+innerRadius*Math.cos(currentAngle)
y2 = centerPointY+innerRadius*Math.sin(currentAngle)
x3 = centerPointX+outerRadius*Math.cos(currentAngle2)
y3 = centerPointY+outerRadius*Math.sin(currentAngle2)
x4 = centerPointX+innerRadius*Math.cos(currentAngle2)
y4 = centerPointY+innerRadius*Math.sin(currentAngle2)
如何利用现有信息生成具有完美圆曲线的路径元素

(PS)我对SVG还不熟悉,如果你想帮助我使用d=的正确语法,那将很酷,但我可以自己编写。我想要帮助的挑战其实更多的是与贝齐尔有关

更新/解决方案

使用下面的答案下面的指导是我实际使用的功能:

annularSector = (centerX,centerY,startAngle,endAngle,innerRadius,outerRadius) ->               
    startAngle  = degreesToRadians startAngle+180
    endAngle    = degreesToRadians endAngle+180
    p           = [ 
        [ centerX+innerRadius*Math.cos(startAngle),     centerY+innerRadius*Math.sin(startAngle) ]
        [ centerX+outerRadius*Math.cos(startAngle),     centerY+outerRadius*Math.sin(startAngle) ]
        [ centerX+outerRadius*Math.cos(endAngle),       centerY+outerRadius*Math.sin(endAngle) ]
        [ centerX+innerRadius*Math.cos(endAngle),       centerY+innerRadius*Math.sin(endAngle) ] 
    ]
    angleDiff   = endAngle - startAngle
    largeArc    = (if (angleDiff % (Math.PI * 2)) > Math.PI then 1 else 0)
    commands    = []

    commands.push "M" + p[0].join()
    commands.push "L" + p[1].join()
    commands.push "A" + [ outerRadius, outerRadius ].join() + " 0 " + largeArc + " 1 " + p[2].join()
    commands.push "L" + p[3].join()
    commands.push "A" + [ innerRadius, innerRadius ].join() + " 0 " + largeArc + " 0 " + p[0].join()
    commands.push "z"

    return commands.join(" ")   
演示: 用法:

环形搜索器(myPathElement{
centerX:100,centerY:150,
起点度数:190,终点度数:230,
内半径:75,外半径:100
});
核心职能:

//选项:
//-centerX,centerY:圆中心的坐标
//-起始角度、结束角度:在这些角度之间顺时针填充
//-内半径,外半径:距中心的距离
//-厚度:内半径和外半径之间的距离
//您应该只指定半径和厚度的三分之二
功能环形分离器(路径、选项){
var opts=带有默认值的选项(选项);
var p=[//点
[opts.cx+opts.r2*Math.cos(opts.startRadians),
opts.cy+opts.r2*Math.sin(opts.startRadians)],
[opts.cx+opts.r2*Math.cos(opts.closeRadians),
opts.cy+opts.r2*Math.sin(opts.closeRadians)],
[opts.cx+opts.r1*Math.cos(opts.closeRadians),
opts.cy+opts.r1*Math.sin(opts.closeRadians)],
[opts.cx+opts.r1*Math.cos(opts.startRadians),
opts.cy+opts.r1*Math.sin(opts.startRadians)],
];
var angleDiff=opts.closeRadians-opts.startRadians;
var largeArc=(angleDiff%(Math.PI*2))>Math.PI?1:0;
var-cmds=[];
cmds.push(“M”+p[0].join());//移动到P0
push(“A”+[opts.r2,opts.r2,0,largeArc,1,p[1]].join());//弧到P1
cmds.push(“L”+p[2].join());//行到P2
push(“A”+[opts.r1,opts.r1,0,largeArc,0,p[3]].join());//弧到P3
cmds.push(“z”);//关闭路径(到P0的行)
path.setAttribute('d',cmds.join('');
带有默认值的功能选项(o){
//创建一个新对象,这样我们就不会改变原始对象
var o2={
cx:o.centerX | | 0,
赛:o.centerY | | 0,
StartDians:(o.startDegrees | | 0)*Math.PI/180,
闭合弧度:(o.endDegrees | | 0)*Math.PI/180,
};
var t=o.厚度!==未定义?o.厚度:100;
如果(o.innerRadius!==未定义)o2.r1=o.innerRadius;
如果(o.outerRadius!==未定义)o2.r1=o.outerRadius-t;
否则o2.r1=200-t;
如果(o.outerRadius!==未定义)o2.r2=o.outerRadius;
否则o2.r2=o2.r1+t;

如果(o2.R1当然,您需要一条路径来勾勒出该形状,对吗?沿着入口有一条弧并带有一个非常宽且有封顶的线条是不够的…对吗?另外,请注意,这完全只使用贝塞尔二次贝塞尔手柄。但是,可以完全使用SVG来完成。您想要贝塞尔近似值还是基于精确圆弧的解tion?Arc也有效!只要是大纲就行。亲爱的downvoter,有什么评论吗?伙计,你太过火了!谢谢!@Freshyeball不客气。请注意,我刚刚更新了演示,答案稍微干净了一点。(重新排序点,以便最后的
closePath
命令绘制一条直线,并使用
array.join()
而不是字符串串接,以获得更高效、更少字符和更清晰的代码。很酷,您还应该检查end是否大于start(即,如果小于start,则向end添加360度)。例如
var\u end=(end
(可能值得检查起点比终点大多少,或者先将它们归一化为(即角度%Math.PI*2)