如何计算圆弧的 SVG 路径
给定一个以 (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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
扩展 @wdebeaum 的出色答案,这里有一种生成弧形路径的方法:
中使用
在 html
Live demo 和
Expanding on @wdebeaum's great answer, here's a method for generating an arced path:
to use
and in your html
Live demo
您想要使用椭圆
A
rc命令。不幸的是,这需要您指定起点和终点的笛卡尔坐标(x,y),而不是您拥有的极坐标(半径,角度),因此您必须做一些数学运算。这是一个应该可以工作的 JavaScript 函数(尽管我还没有测试过它),我希望它是相当不言自明的:哪些角度对应于哪些时钟位置将取决于坐标系;只需根据需要交换和/或否定 sin/cos 项即可。
arc 命令具有以下参数:
对于第一个示例:
rx
=ry
=25 和x-axis-rotation
=0,因为您想要一个圆而不是一个椭圆。您可以使用上面的函数计算起始坐标(您应该M
)和结束坐标(x, y),分别产生 (200, 175) 和大约 (182.322, 217.678) 。到目前为止,考虑到这些限制,实际上可以绘制四个弧线,因此两个标志选择其中之一。我猜你可能想在角度减小的方向上画一个小弧(意味着large-arc-flag
=0)(意味着sweep-flag
=0) )。总而言之,SVG 路径是:对于第二个示例(假设您的意思是朝同一方向移动,因此是一个大弧线),SVG 路径是:
再次强调,我还没有测试过这些。
(编辑于 2016 年 6 月 1 日)如果您像 @clocksmith 一样想知道他们为什么选择这个 API,请查看 实现说明。他们描述了两种可能的弧参数化,“端点参数化”(他们选择的一种)和“中心参数化”(就像问题所使用的那样)。在“端点参数化”的描述中,他们说:
所以基本上这是弧被视为更大路径的一部分而不是它们自己的单独对象的副作用。我想如果你的 SVG 渲染器不完整,它可以跳过任何它不知道如何渲染的路径组件,只要它知道它们需要多少个参数。或者它可能允许使用许多组件并行渲染路径的不同块。或者也许他们这样做是为了确保舍入误差不会沿着复杂路径的长度累积。
实现注释对于原始问题也很有用,因为它们有更多的数学伪代码用于在两个参数化之间进行转换(当我第一次写这个答案时我没有意识到)。
You want to use the elliptical
A
rc command. Unfortunately for you, this requires you to specify the Cartesian coordinates (x, y) of the start and end points rather than the polar coordinates (radius, angle) that you have, so you have to do some math. Here's a JavaScript function which should work (though I haven't tested it), and which I hope is fairly self-explanatory:Which angles correspond to which clock positions will depend on the coordinate system; just swap and/or negate the sin/cos terms as necessary.
The arc command has these parameters:
For your first example:
rx
=ry
=25 andx-axis-rotation
=0, since you want a circle and not an ellipse. You can compute both the starting coordinates (which you shouldM
ove to) and ending coordinates (x, y) using the function above, yielding (200, 175) and about (182.322, 217.678), respectively. Given these constraints so far, there are actually four arcs that could be drawn, so the two flags select one of them. I'm guessing you probably want to draw a small arc (meaninglarge-arc-flag
=0), in the direction of decreasing angle (meaningsweep-flag
=0). All together, the SVG path is:For the second example (assuming you mean going the same direction, and thus a large arc), the SVG path is:
Again, I haven't tested these.
(edit 2016-06-01) If, like @clocksmith, you're wondering why they chose this API, have a look at the implementation notes. They describe two possible arc parameterizations, "endpoint parameterization" (the one they chose), and "center parameterization" (which is like what the question uses). In the description of "endpoint parameterization" they say:
So basically it's a side-effect of arcs being considered as part of a larger path rather than their own separate object. I suppose that if your SVG renderer is incomplete it could just skip over any path components it doesn't know how to render, as long as it knows how many arguments they take. Or maybe it enables parallel rendering of different chunks of a path with many components. Or maybe they did it to make sure rounding errors didn't build up along the length of a complex path.
The implementation notes are also useful for the original question, since they have more mathematical pseudocode for converting between the two parameterizations (which I didn't realize when I first wrote this answer).
我稍微修改了opsb的答案并为圆扇区提供了支持填充。
JS
HTML
I slightly modified the answer of opsb and made in support fill for the circle sector.
JS
HTML
我正在对 @opsb 的答案添加一个小扩展。
如果您想将此弧转换为切片(以允许填充),我们可以稍微修改代码:
就这样吧!
I am adding a small expansion to @opsb's answer.
If you wanted to convert this arc into a slice (to allow for fill) we can modify the code slightly:
and there you go!
如果不必使用 arc,绘制部分圆的一个更简单的解决方案是使用 SVG
的lines-dasharray
。将破折号数组分为两个元素,并将它们的范围缩放到所需的角度。可以使用
Stroke-dashoffset
调整起始角度。看不到任何余弦。
带解释的完整示例:
https://codepen.io/mjurczyk/pen/wvBKOvP
If using arc is not obligatory, a far simpler solution to draw a part-circle is to use
stroke-dasharray
of SVG<circle>
.Divide dash array into two elements, and scale their range to the desired angle. Starting angle can be adjusted using
stroke-dashoffset
.Not a single cosine in sight.
Full example with explanations:
https://codepen.io/mjurczyk/pen/wvBKOvP
opsb的答案很简洁,但中心点不准确,而且,正如Jithin指出的,如果角度是360度,那么什么也画不出来。
Jithin 修复了 360 度问题,但如果您选择小于 360 度,那么您将得到一条闭合圆弧循环的线,这不是必需的。
我修复了这个问题,并在下面的代码中添加了一些动画:
opsb's answers is neat, but the center point is not accurate, moreover, as Jithin noted, if the angle is 360, then nothing is drawn at all.
Jithin fixed the 360 issue, but if you selected less than 360 degree, then you'll get a line closing the arc loop, which is not required.
I fixed that, and added some animation in the code below:
ES6版本:
ES6 version:
我想对 @Ahtenus 的答案发表评论,特别是 Ray Hulha 的评论,他说 codepen 没有显示任何弧线,但我的声誉不够高。
此 codepen 无法工作的原因是其 html 有错误,笔画宽度为零。
我修复了它并在此处添加了第二个示例: http://codepen.io/AnotherLinuxUser/pen/QEJmkN。
html:
相关 CSS:
javascript:
I wanted to comment on @Ahtenus answer, specifically on Ray Hulha comment saying the codepen does not show any arc, but my reputation is not high enough.
The reason for this codepen not working is that its html is faulty with a stroke-width of zero.
I fixed it and added a second example here : http://codepen.io/AnotherLinuxUser/pen/QEJmkN.
The html :
The relevant CSS :
The javascript :
一张图片和一些 Python
只是为了更好地澄清并提供另一种解决方案。
Arc
[A< /code>] 命令使用当前位置作为起点,因此您必须使用
Moveto
首先是 [M] 命令。那么
Arc
的参数如下:如果我们定义以下 svg 文件:
您将使用
M
设置起点,使用的参数
xf
和yf
设置终点一个。我们正在寻找圆,因此我们将
rx
设置为ry
这样做基本上现在它会尝试找到所有相交的半径为rx
的圆起点和终点。您可以在这篇文章中获得更详细的解释是我写的。
An image and some Python
Just to clarify better and offer another solution.
Arc
[A
] command use the current position as a starting point so you have to useMoveto
[M] command first.Then the parameters of
Arc
are the following:If we define for example the following svg file:
You will set the starting point with
M
the ending point with the parametersxf
andyf
ofA
.We are looking for circles so we set
rx
equal tory
doing so basically now it will try to find all the circle of radiusrx
that intersect the starting and end point.You can have a more detailed explanation in this post that I wrote.
wdebeaum 的原始 PolarToCartesian 函数是正确的:
使用以下方式反转起点和终点:
(对我而言)令人困惑,因为这会反转扫描标志。使用:
使用sweep-flag =“0”绘制“正常”逆时针弧线,
我认为这更直接。
请参阅 https://developer.mozilla.org/en-US/文档/Web/SVG/教程/路径
The orginal polarToCartesian function by wdebeaum is correct:
Reversing of start and end points by using:
Is confusing (to me) because this will reverse the sweep-flag. Using:
with the sweep-flag = "0" draws "normal" counter-clock-wise arcs,
which I think is more straight forward.
See https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
基于所选答案的 ReactJS 组件:
ReactJS component based on the selected answer:
对@opsb 的答案稍作修改。我们不能用这种方法画一个完整的圆。即如果我们给出 (0, 360) 它根本不会绘制任何东西。因此,做了一些小小的修改来解决这个问题。显示有时达到 100% 的分数可能很有用。
A slight modification to @opsb's answer. We cant draw a full circle with this method. ie If we give (0, 360) it will not draw anything at all. So a slight modification made to fix this. It could be useful to display scores that sometimes reach 100%.
我会使用其他答案中的代码,它们似乎都是相互复制的,但我会将起点设为起始角度的函数,将终点设为结束角度的函数。
我将通过使用绝对值使大弧标志与顺序无关,并通过对 360 度进行模运算使角度与数值大小无关。
向威利道歉;我还没读到最后,发现他也发现了同样的事情。如果您喜欢我的帖子,请为他点赞!
I'd use the code from other answers, where they all appear to be copying from each other, but I would make the start point a function of the start angle and the end point a function of the end angle.
I would make the large arc flag independent of the order by using absolute value, and make the angles independent of numerical magnitude by working modulo 360 degrees.
Apologies to Wiley; I hadn't read to the end and see he has spotted the same thing. If you like my post, upvote his instead!
可以使用我为上面的答案所做的JSFiddle代码:
https://jsfiddle.net/tyw6nfee/
您 需要做的是更改最后一行 console.log 代码并为其提供您自己的参数:
you can use JSFiddle code i made for answer above:
https://jsfiddle.net/tyw6nfee/
all you need to do is change last line console.log code and give it your own parameter:
PHP 有人吗?
将接受的答案转换为 PHP 代码。帮助在服务器上生成弧线。
PHP Anyone?
Converted the accepted answer to PHP code. Helps in generating the arc on the server.
以下是一个变体,
0
位于北位置,并且在 SVG 坐标系中顺时针扫描角度(即左上角的 0,0)。它生成一个可分配给 img.src 的 SVG 数据 URI。它更新了largeArcFlag 和sweepFlag 的计算。The following is a variation that has
0
in the north position and the angle sweep clockwise in SVG coordinate system (i.e. 0,0 on the top-left corner). It generates an SVG data-URI which can be assigned to an img.src. It has updated calculations for largeArcFlag and sweepFlag.