【发布时间】:2011-11-19 11:19:37
【问题描述】:
我不确定如何在 SVG 中绘制一个空心圆。
我想要一个用颜色填充然后有黑色轮廓的环形。
我想这样做的方式是有 2 个圆,一个比另一个半径小。问题是当我填充它们时,如何使较小的圆圈采用与其所在位置相同的填充颜色?
【问题讨论】:
标签: svg
我不确定如何在 SVG 中绘制一个空心圆。
我想要一个用颜色填充然后有黑色轮廓的环形。
我想这样做的方式是有 2 个圆,一个比另一个半径小。问题是当我填充它们时,如何使较小的圆圈采用与其所在位置相同的填充颜色?
【问题讨论】:
标签: svg
只需使用fill="none",然后只会绘制stroke(轮廓)。
<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>
如果你想要两种颜色,也可以这样:
<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>
【讨论】:
MDragon00 的回答有效,但内圈和外圈没有完全对齐(例如居中)。
我稍微修改了他的方法,使用 4 个半圆弧(2 个外部和 2 个内部反向)来完全正确地对齐。
<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
-->
【讨论】:
感谢 Chasbeen,我想出了如何在 SVG 中制作真正的戒指/甜甜圈。请注意,外圈实际上并没有闭合,这仅在您使用笔画时才明显。当您有许多同心环时非常有用,尤其是当它们是交互式的(例如,使用 CSS 悬停命令)时。
对于绘图命令...
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 来模拟交互性。请注意,起点(顶部)缺少一个像素,只有在添加笔画时才会出现。
编辑: 找到了这个SO answer(更好的是this answer),它描述了如何获得一般的空内脏
【讨论】:
m x 值是1 而不是0:m 1, outerRadius-innerRadius
您可以按照 SVG 规范通过使用包含两个组件和 fill-rule="evenodd" 的路径来执行此操作。这两个组件是连接形成一个圆的半圆弧(在下面的“d”属性中,它们每个都以“z”结尾)。内圈内的区域不计入形状的一部分,因此交互性很好。
稍微解码下面,“340 260”是外圆的顶部中间,“290 290”是外圆的半径(两倍),“340 840”是底部中间外圆,“340 492”是内圆的顶部中间,“58 58”是内圆的半径(两倍),“340 608”是内圆的底部中间。
<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)">
<title>This will only display on the donut</title>
</path>
</svg>
【讨论】:
这是经典的甜甜圈形状 我不确定您是否正在尝试使用标准 SVG 或生成 SVG 的 JavaScript 来实现这一点 该目标可以通过在单个路径定义中包含相对“moveto”命令来实现
然后单击交互式示例右侧的“甜甜圈洞”。 至少您可以看到制作红色甜甜圈的路径定义。
【讨论】:
这是一个创建贝塞尔曲线的例程,该曲线尽可能接近圆形。一条完整的圆圈需要其中四个。
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]});
}
【讨论】: