如何将SVG中的'C'曲线转换为三次贝塞尔曲线列表?

5

以下是我要翻译的内容:

我有一个如下的路径:

d="m 0,0 38.913,455.481 c 7.122,83.37 6.816,164.779 13.005,236.077 18.924,218.078 232.099,308.663 268.399,493.918 16.874,86.119 -37.253,229.874 -42.144,323.022 -7.527,143.381 69.579,142.669 104.526,244.648"

我不太明白它是如何表示的。

我猜它被转换为多个简单的三次贝塞尔曲线列表,但是怎么做呢?每次应该将什么作为控制点、起点和终点?

这里的坐标到底是相对的吗?相对于什么?

我完全不了解SVG图形,而且(在我看来)w3的参考资料并没有给出足够详细的信息。

如果可以帮助我,我的目标是使用JavaScript在画布上逐点表示此曲线。


1
阅读规范有什么难的 - 它非常清晰明了:http://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands - Michael Mullany
2
其实并不是。一开始我以为这是一个有12个点的贝塞尔曲线(12阶),于是我实现了它,后来才意识到应该将其分成多个三次曲线。所以我的观点就像我在评论中提到的那样,这一章写得很差,缺乏关键细节。 - Sami
我同意,规范对于在C或c后面跟随超过三个点时的含义并不清晰。 - I. J. Kennedy
2个回答

2
你似乎使用的是三次贝塞尔曲线,而不是二次曲线。规范文本解释了控制点以及它们相对于什么(通常是前一个移动/直线/曲线的结束点)。

这里举个例子,c 后面的三个点是控制点1、控制点2和结束点?第一个起始点是 m 后面的第二个点? - Sami
第一个问题的答案是肯定的,对于第二个问题中的“第二点”我不太确定你的意思。 - Robert Longson
只是为了确保,如果我理解正确,c 1,1 2,2 3,3 4,4 5,5 6,6 会变成 C 1,1 2,2 3,3 C 7,7 8,8 9,9 - Sami
是的,为什么不创建一个SVG文件并尝试一下呢? - Robert Longson

1

1. 通过yqnn的SVG路径编辑器进行转换

重写您的路径数据d属性的简单方法是将字符串插入yqnn的SVG路径编辑器中,并
切换缩小选项复选框两次。

所有省略的命令字母(用于重复和隐式命令)都将添加到更易读的d字符串中。

2. 通过getPathData()进行转换

getPathData()尚未得到任何主流浏览器的支持。
因此,您需要像Jarek Foksa的pathdata polyfill.这样的polyfill。

  1. 使用getPathData()解析路径。
    所有重复或隐式命令将被拆分为单独的命令:
    隐式相对l lineto:
m 0,0 38.913,455.481 
// result:
M 0,0 l 38.913,455.481   

d 属性中的第一个 m 命令实际上总是绝对的。由于我们已经转换了隐式的 l 命令,因此我们可以将第一个 moveto 更改为大写字母 M 命令字母(可以方便路径连接)。

重复的 c (三次贝塞尔曲线)

c 7.122 83.37 6.816 164.779 13.005 236.077   
18.924 218.078 232.099 308.663 268.399 493.918 
16.874 86.119 -37.253 229.874 -42.144 323.022 
-7.527 143.381 69.579 142.669 104.526 244.648  
// result:
c 7.122 83.37 6.816 164.779 13.005 236.077   
c 18.924 218.078 232.099 308.663 268.399 493.918 
c 16.874 86.119 -37.253 229.874 -42.144 323.022 
c -7.527 143.381 69.579 142.669 104.526 244.648
  1. 使用 setPathData() 应用 pathData

let pathData = path.getPathData();
path.setPathData(pathData);
output.value = path.getAttribute('d');
svg{
height:20em
}

textarea{
width:100%;
min-height:20em;
}
<script src="https://cdn.jsdelivr.net/npm/path-data-polyfill@1.0.4/path-data-polyfill.min.js"></script>


<svg viewBox="0 0 382.7 1753.15">
        <path id="path" d="m 0,0 38.913,455.481 c 7.122,83.37 6.816,164.779 13.005,236.077 18.924,218.078 232.099,308.663 268.399,493.918 16.874,86.119 -37.253,229.874 -42.144,323.022 -7.527,143.381 69.579,142.669 104.526,244.648&quot;" fill="none" stroke="#000000" stroke-width="2" />
</svg>

<textarea id="output"></textarea>

3. 手动方法

你只需要知道每个命令类型的值/参数数量,并相应地将命令值拆分成块:

M:2个值 - 后续值被视为隐式的L linetos。
LT:2个值
VH:1个值
C:6个值
SQ:4个值
A:7个值


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接