160

简短的问题:使用 SVG 路径,我们可以绘制 99.99% 的圆并显示,但是当它是圆的 99.99999999% 时,则不会显示圆。如何修复?

下面的SVG路径可以画出99.99%的圆:(在http://jsfiddle.net/DFhUF/1381/上试试看是看到4个圆弧还是只看到2个圆弧,但是注意如果是IE的话是用 VML 渲染,而不是 SVG,但有类似的问题)

M 100 100 a 50 50 0 1 0 0.00001 0

但是当它是一个圆的 99.99999999% 时,什么都不会显示?

M 100 100 a 50 50 0 1 0 0.00000001 0    

这与 100% 的圆相同(它仍然是一个圆弧,不是吗,只是一个非常完整的圆弧)

M 100 100 a 50 50 0 1 0 0 0 

这怎么能解决?原因是我使用一个函数来绘制弧的百分比,如果我需要“特殊情况”一个 99.9999% 或 100% 的弧来使用圆函数,那就有点傻了。

同样,在 jsfiddle 上使用 RaphaelJS 的测试用例位于http://jsfiddle.net/DFhUF/1381/
(如果它是 IE 8 上的 VML,则即使第二个圆圈也不会显示......你必须将其更改为0.01)


更新:

这是因为我正在为我们的系统中的分数绘制弧线,所以 3.3 分得到 1/3 的圆。0.5 得到半个圆,9.9 分得到 99% 的圆。但是,如果我们的系统中有 9.99 的分数怎么办?我是否必须检查它是否接近圆的 99.999%,并相应地使用arc函数或circle函数?那么9.9987的分数呢?使用哪一个?需要知道什么样的分数会映射到“太完整的圆”并切换到圆函数,而当它是圆的“某个 99.9%”或 9.9987 分数时,再使用弧函数,这很可笑.

4

12 回答 12

457

我知道这在游戏中有点晚了,但我记得这个问题是新问题,我有类似的困境,如果有人还在寻找一个,我偶然找到了“正确”的解决方案:

<path 
    d="
    M cx cy
    m -r, 0
    a r,r 0 1,0 (r * 2),0
    a r,r 0 1,0 -(r * 2),0
    "
/>

换句话说,这:

<circle cx="100" cy="100" r="75" />

可以通过以下方式实现:

  <path 
        d="
        M 100, 100
        m -75, 0
        a 75,75 0 1,0 150,0
        a 75,75 0 1,0 -150,0
        "
  />

诀窍是有两个弧,第二个从第一个离开的地方开始,并使用负直径返回到原始弧的起点。

它不能在一个弧中作为一个完整的圆完成的原因(我只是在推测)是因为你会告诉它从自身(比如说 150,150)到自身(150,150)绘制一条弧,它会渲染作为“哦,我已经在那里,不需要弧线!”。

我提供的解决方案的好处是:

  1. 很容易从圆直接转换为路径,并且
  2. 两条弧线没有重叠(如果您使用标记或图案等可能会导致问题)。这是一条干净的连续线,尽管被分成两部分。

如果他们只允许文本路径接受形状,这一切都无关紧要。但我认为他们正在避免这种解决方案,因为像圆形这样的形状元素在技术上没有“起点”。

jsfiddle 演示:http: //jsfiddle.net/crazytonyi/mNt2g/

更新:

如果您使用路径作为textPath参考并且希望文本呈现在弧的外边缘,您将使用完全相同的方法,但将扫描标志从 0 更改为 1,以便它处理外部路径作为表面而不是内部(想象1,0有人坐在中心并围绕自己画一个圆圈,而1,1有人在半径距离处围绕中心行走并将粉笔拖到他们旁边,如果这有帮助的话)。这是上面的代码,但有变化:

<path 
    d="
    M cx cy
    m -r, 0
    a r,r 0 1,1 (r * 2),0
    a r,r 0 1,1 -(r * 2),0
    "
/>
于 2012-05-07T05:58:17.833 回答
38

XAML 的弧也是如此。只需用 a 闭合 99.99% 的弧,Z你就得到了一个圆!

于 2011-04-21T00:41:06.557 回答
23

参考 Anthony 的解决方案,这里有一个获取路径的函数:

function circlePath(cx, cy, r){
    return 'M '+cx+' '+cy+' m -'+r+', 0 a '+r+','+r+' 0 1,0 '+(r*2)+',0 a '+r+','+r+' 0 1,0 -'+(r*2)+',0';
}
于 2015-01-12T15:21:24.413 回答
12

完全不同的方法:

除了摆弄路径以在 svg 中指定弧线,您还可以采用圆形元素并指定 stroke-dasharray,在伪代码中:

with $score between 0..1, and pi = 3.141592653589793238

$length = $score * 2 * pi * $r
$max = 7 * $r  (i.e. well above 2*pi*r)

<circle r="$r" stroke-dasharray="$length $max" />

它的简单性是多弧路径方法的主要优势(例如,在编写脚本时,您只需插入一个值,就可以完成任何弧长)

圆弧从最右边的点开始,可以使用旋转变换来移动。

注意:Firefox 有一个奇怪的错误,即忽略超过 90 度或更多的旋转。因此,要从顶部开始弧线,请使用:

<circle r="$r" transform="rotate(-89.9)" stroke-dasharray="$length $max" />
于 2015-01-08T00:44:34.477 回答
6

对于像我这样正在寻找路径转换的椭圆属性的人:

const ellipseAttrsToPath = (rx,cx,ry,cy) =>
`M${cx-rx},${cy}a${rx},${ry} 0 1,0 ${rx*2},0a${rx},${ry} 0 1,0 -${rx*2},0 Z`
于 2017-05-16T12:04:48.843 回答
5

Adobe Illustrator 使用像 SVG 一样的贝塞尔曲线,而对于圆形,它会创建四个点。您可以使用两个椭圆弧命令创建一个圆......但是对于 SVG 中的一个圆,我会使用<circle />:)

于 2011-04-21T02:42:09.007 回答
5

在 Anthony 和 Anton 的回答的基础上,我加入了旋转生成的圆圈而不影响其整体外观的能力。如果您使用动画的路径并且您需要控制它的开始位置,这将非常有用。

function(cx, cy, r, deg){
    var theta = deg*Math.PI/180,
        dx = r*Math.cos(theta),
        dy = -r*Math.sin(theta);
    return "M "+cx+" "+cy+"m "+dx+","+dy+"a "+r+","+r+" 0 1,0 "+-2*dx+","+-2*dy+"a "+r+","+r+" 0 1,0 "+2*dx+","+2*dy;
}
于 2016-12-29T21:38:11.780 回答
4

我在这里做了一个jsfiddle:

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;       
}
console.log(describeArc(255,255,220,134,136))

关联

您需要做的就是更改 console.log 的输入并在控制台中获取结果

于 2017-10-04T08:04:28.327 回答
3

写成一个函数,它看起来像这样:

function getPath(cx,cy,r){
  return "M" + cx + "," + cy + "m" + (-r) + ",0a" + r + "," + r + " 0 1,0 " + (r * 2) + ",0a" + r + "," + r + " 0 1,0 " + (-r * 2) + ",0";
}
于 2016-11-01T09:00:40.890 回答
2

使用两个圆弧命令画一个完整的圆是个好主意。

通常,我使用椭圆或圆形元素来绘制一个完整的圆。

于 2012-09-08T08:34:13.667 回答
2

这些答案太复杂了。

一种更简单的方法来做到这一点,而无需创建两条弧线或转换到不同的坐标系..

这假设您的画布区域具有 widthw和 height h

`M${w*0.5 + radius},${h*0.5}
 A${radius} ${radius} 0 1 0 ${w*0.5 + radius} ${h*0.5001}`

只需使用“长弧”标志,即可填充完整标志。然后使圆弧成为整个圆的 99.9999%。视觉上是一样的。只需从圆的最右边点开始圆(从中心直接水平的一个半径),即可避免扫描标志。

于 2018-05-26T21:09:01.093 回答
1

另一种方法是使用两个三次贝塞尔曲线。这适用于使用不能识别 svg arc 参数的pocketSVG的 iOS用户。

C x1 y1、x2 y2、xy(或 c dx1 dy1、dx2 dy2、dx dy)

三次贝塞尔曲线

此处的最后一组坐标 (x,y) 是您希望线结束的位置。另外两个是控制点。(x1,y1) 是曲线起点的控制点,(x2,y2) 是曲线终点的控制点。

<path d="M25,0 C60,0, 60,50, 25,50 C-10,50, -10,0, 25,0" />
于 2016-03-01T19:19:18.740 回答