在SVG中画一个空心圆


Draw a hollow circle in SVG

我不确定如何在SVG中绘制空心圆。

我想要一个充满颜色的环形,然后有一个黑色的轮廓。

我考虑的方式是有两个圆,一个圆的半径小于另一个圆。 问题是,当我填充它们时,如何使较小的圆与它所在的位置具有相同的填充颜色?


只需使用fill="none",然后仅绘制stroke(轮廓)。

1
2
3
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="none" />
</svg>

如果要两种颜色,也可以这样:

1
2
3
4
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="none" />
   <circle cx="100" cy="50" r="39" stroke="red" stroke-width="2" fill="none" />
</svg>


感谢Chasbeen,我弄清楚了如何在SVG中制作出真正的戒指/甜甜圈。请注意,外圈实际上不是封闭的,只有在使用笔触时才会明显。当您有许多同心环时,特别是在它们是交互式的时(例如,使用CSS悬停命令),该功能非常有用。

对于绘制命令...

1
2
3
4
5
6
7
M cx, cy // Move to center of ring
m 0, -outerRadius // Move to top of ring
a outerRadius, outerRadius, 0, 1, 0, 1, 0 // Draw outer arc, but don't close it
Z // default fill-rule:even-odd will help create the empty innards
m 0 outerRadius-innerRadius // Move to top point of inner radius
a innerRadius, innerRadius, 0, 1, 1, -1, 0 // Draw inner arc, but don't close it
Z // Close the inner ring. Actually will still work without, but inner ring will have one unit missing in stroke

JSFiddle-包含多个环和CSS以模拟交互性。请注意,不利的一面是,在起点(顶部)缺少单个像素,只有在添加笔触时才存在。

编辑:
找到了这样的答案(更好的是,这个答案),它描述了如何获得空的内脏。


MDragon00的答案有效,但是内圈和外圈没有完全对齐(例如居中)。

我使用4个半圆弧(反向的2个外部弧形和2个内部的反向弧形)稍微修改了他的方法,以使对齐方式完全正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<svg width="100" height="100">
  <path d="M 50 10 A 40 40 0 1 0 50 90 A 40 40 0 1 0 50 10 Z M 50 30 A 20 20 0 1 1 50 70 A 20 20 0 1 1 50 30 Z" fill="#0000dd" stroke="#00aaff" stroke-width="3" />
</svg>

<!--

Using this path definition as d:

M centerX (centerY-outerRadius)
A outerRadius outerRadius 0 1 0 centerX (centerY+outerRadius)
A outerRadius outerRadius 0 1 0 centerX (centerY-outerRadius)
Z
M centerX (centerY-innerRadius)
A innerRadius innerRadius 0 1 1 centerX (centerY+innerRadius)
A innerRadius innerRadius 0 1 1 centerX (centerY-innerRadius)
Z

-->


这是经典的甜甜圈形状
我不确定您是否要尝试使用标准SVG或生成SVG的JavaScript来实现这一目标
可以通过在单个路径定义中包含相对的" moveto"命令来实现该目标。

然后单击交互式示例右侧的"甜甜圈孔"。
至少您可以看到制作红色甜甜圈的路径定义。


您可以按照SVG规范执行此操作,方法是使用包含两个组件和fill-rule =" evenodd"的路径。这两个分量是半圆弧,它们连接形成一个圆(在下面的" d"属性中,它们各自以" z"结尾)。内圆内的面积不算作形状的一部分,因此交互性很好。

为了稍微说明一下," 340 260"是外圆的顶部中间," 290 290"是外圆的半径(两倍)," 340 840"是外圆的底部中间," 340 492"是内圆的顶部中间," 58 58"是内圆的半径(两倍)," 340 608"是内圆的底部中间。

1
2
3
4
5
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" d="M340 260A290 290 0 0 1 340 840A290 290 0 0 1 340 260zM340 492A58 58 0 0 1 340 608A58 58 0 0 1 340 492z" stroke-width="4" stroke="rgb(0,0,0)" fill="rgb(0,0,255)">
        This will only display on the donut
    </path>
</svg>

这是一个创建贝塞尔曲线的例程,该弧形尽可能接近一个圆。一个完整的圆圈需要四个路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 BezierCurve BezierArc(double ox, double oy, double r, double thetaa, double thetab)
    {
        double theta;
        double cpx[4];
        double cpy[4];
        int i;
        int sign = 1;

        while (thetaa > thetab)
            thetab += 2 * Pi;
        theta = thetab - thetaa;
        if (theta > Pi)
        {
            theta = 2 * Pi - theta;
            sign = -1;
        }
        cpx[0] = 1;
        cpy[0] = 0;
        cpx[1] = 1;
        cpy[1] = 4.0 / 3.0 * tan(theta / 4);
        cpx[2] = cos(theta) + cpy[1] * sin(theta);
        cpy[2] = sin(theta) - cpy[1] * cos(theta);
        cpx[3] = cos(theta);
        cpy[3] = sin(theta);
        cpy[1] *= sign;
        cpy[2] *= sign;
        cpy[3] *= sign;

        for (i = 0; i < 4; i++)
        {
            double xp = cpx[i] * cos(thetaa) + cpy[i] * -sin(thetaa);
            double yp = cpx[i] * sin(thetaa) + cpy[i] * cos(thetaa);
            cpx[i] = xp;
            cpy[i] = yp;
            cpx[i] *= r;
            cpy[i] *= r;
            cpx[i] += ox;
            cpy[i] += oy;
        }

        return BezierCurve({cpx[0], cpy[0]},{cpx[1], cpy[1]}, {cpx[2], cpy[2]}, {cpx[3], cpy[3]});
    }