SVG:将圆弧转换为三次贝塞尔曲线
SVG: Convert Arcs to Cubic Bezier
我正在尝试做一些我认为非常简单的事情:用三次贝塞尔曲线替换 SVG 路径中的所有圆弧。
这个:http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes 并没有真正帮助我,因为它并没有真正说明转换。
我知道如何制作简单的 Arcs,但是 SVG Arcs 确实有很多参数。
所以我需要的基本上只是一个算法:
rx ry x-axis-rotation large-arc-flag sweep-flag x y
(也是圆弧的起点)
并计算:
x1 y1 x2 y2 x y
(当然是起点,x和y保持相同的值...)
有人知道这样的事情吗?
提前致谢! :-)
事实证明这是不可能的。我的意思是,至少在数学上。你不能用普通的三次贝塞尔曲线做圆弧,你总是会出错,所以根据圆弧的角度,你可能需要不止一条贝塞尔曲线。
也就是说,三次贝塞尔曲线非常适用于四分之一圆弧,所以如果你的弧比它小,你可以使用一条曲线,如果你有更宽的弧,你可以简单地将它除以一个合理的数字(在四分之一和半圆之间?使用两条曲线。在半到三夸脱之间?使用三个。全圆?四个曲线。非常简单)。
那么,这是多少工作量?事实证明,如果你必须从头开始:a fair bit of work,但你可以直接跳到 "okay so what is the final formula I need" 然后它变得相对简单。
如果我们有角度 phi
,则弧的三次曲线近似值,前提是我们将弧的起点与 x 轴对齐(这样弧从 y=0 开始,并且 运行s 从那里逆时针),我们有一个圆弧半径 R
,是:
start coordinate = {
x: R,
y: 0
}
control point 1 = {
x: R,
y: R * 4/3 * tan( phi / 4)
}
control point 2 = {
x: R * ( cos(phi) + 4/3 * tan( phi/4 ) * sin(phi) ),
y: R * ( sin(phi) - 4/3 * tan( phi/4 ) * cos(phi) ),
}
end coordinate = {
x: R * cos(phi),
y: R * sin(phi)
}
数学!但实际上只是"plug in angle, get the coordinates we need"。简单!
但是如果我们的圆弧没有与 x 轴对齐怎么办?我们应用一个愚蠢的 "rotate + translate" 来对齐我们的弧线,然后我们 运行 完成后反向 rotation/translation。解释 here.
大多数 SVG 渲染库必须这样做,因为 2D 图形库似乎不直接支持相对于 X 轴旋转的圆弧。
所以你可以在 Batik 中查找代码。或者看看我的 SVG 库中的 arcTo()
方法(它也借鉴了 Batik):
AndroidSVG / SVGAndroidRenderer.java / line 2889
是Java,但应该很容易转换成JS。
您还可以查看 SnapSVG 中的 this function,它可能已被 Adobe Illustrator(由名为 "adobe-webplatform" 的用户托管)以某种方式使用,以将弧形命令转换为立方体命令。它也用于 SVGO(ptimizer)。
我仍在尝试破译它,但该标准实际上对此很有帮助。
您可以查看这些链接:
Arc to Qubic by Dmitry Baranovskiy And also the same implementation by Jarek Foksa.
基于
W3.org
所选答案提供了圆弧的部分解决方案。在研究该主题时,发现了一个 npm for a function extracted from SVG path, to addres excatly this, and here is a quick codesandbox 希望这对某人有帮助
arcpath.setAttribute("d", "M 0 200 A 100 20 0 1 0 100 200");
const options = {
px: 0,
py: 200,
cx: 100,
cy: 200,
rx: 100,
ry: 20,
xAxisRotation: 0,
largeArcFlag: 1,
sweepFlag: 0
};
我正在尝试做一些我认为非常简单的事情:用三次贝塞尔曲线替换 SVG 路径中的所有圆弧。
这个:http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes 并没有真正帮助我,因为它并没有真正说明转换。
我知道如何制作简单的 Arcs,但是 SVG Arcs 确实有很多参数。
所以我需要的基本上只是一个算法:
rx ry x-axis-rotation large-arc-flag sweep-flag x y
(也是圆弧的起点)
并计算:
x1 y1 x2 y2 x y
(当然是起点,x和y保持相同的值...)
有人知道这样的事情吗?
提前致谢! :-)
事实证明这是不可能的。我的意思是,至少在数学上。你不能用普通的三次贝塞尔曲线做圆弧,你总是会出错,所以根据圆弧的角度,你可能需要不止一条贝塞尔曲线。
也就是说,三次贝塞尔曲线非常适用于四分之一圆弧,所以如果你的弧比它小,你可以使用一条曲线,如果你有更宽的弧,你可以简单地将它除以一个合理的数字(在四分之一和半圆之间?使用两条曲线。在半到三夸脱之间?使用三个。全圆?四个曲线。非常简单)。
那么,这是多少工作量?事实证明,如果你必须从头开始:a fair bit of work,但你可以直接跳到 "okay so what is the final formula I need" 然后它变得相对简单。
如果我们有角度 phi
,则弧的三次曲线近似值,前提是我们将弧的起点与 x 轴对齐(这样弧从 y=0 开始,并且 运行s 从那里逆时针),我们有一个圆弧半径 R
,是:
start coordinate = {
x: R,
y: 0
}
control point 1 = {
x: R,
y: R * 4/3 * tan( phi / 4)
}
control point 2 = {
x: R * ( cos(phi) + 4/3 * tan( phi/4 ) * sin(phi) ),
y: R * ( sin(phi) - 4/3 * tan( phi/4 ) * cos(phi) ),
}
end coordinate = {
x: R * cos(phi),
y: R * sin(phi)
}
数学!但实际上只是"plug in angle, get the coordinates we need"。简单!
但是如果我们的圆弧没有与 x 轴对齐怎么办?我们应用一个愚蠢的 "rotate + translate" 来对齐我们的弧线,然后我们 运行 完成后反向 rotation/translation。解释 here.
大多数 SVG 渲染库必须这样做,因为 2D 图形库似乎不直接支持相对于 X 轴旋转的圆弧。
所以你可以在 Batik 中查找代码。或者看看我的 SVG 库中的 arcTo()
方法(它也借鉴了 Batik):
AndroidSVG / SVGAndroidRenderer.java / line 2889
是Java,但应该很容易转换成JS。
您还可以查看 SnapSVG 中的 this function,它可能已被 Adobe Illustrator(由名为 "adobe-webplatform" 的用户托管)以某种方式使用,以将弧形命令转换为立方体命令。它也用于 SVGO(ptimizer)。
我仍在尝试破译它,但该标准实际上对此很有帮助。
您可以查看这些链接:
Arc to Qubic by Dmitry Baranovskiy And also the same implementation by Jarek Foksa.
基于 W3.org
所选答案提供了圆弧的部分解决方案。在研究该主题时,发现了一个 npm for a function extracted from SVG path, to addres excatly this, and here is a quick codesandbox 希望这对某人有帮助
arcpath.setAttribute("d", "M 0 200 A 100 20 0 1 0 100 200");
const options = {
px: 0,
py: 200,
cx: 100,
cy: 200,
rx: 100,
ry: 20,
xAxisRotation: 0,
largeArcFlag: 1,
sweepFlag: 0
};