我使用 SVG 绘制了两条路径线,并将这些元素保存到我的 javascript 代码中的两个变量中:“Line1”和“Line2”,并且我需要将这两条线合并为一个路径元素。有办法做到吗?
您的路径是相对定义的(小写字母)还是绝对定义的(大写字母)? 如果是绝对路径,则连接两条路径很简单,只需附加
d
属性的值即可。 如果你有两条这样的路径:
<path id="Line1" d="M50,50
A30,30 0 0,1 35,20
L100,100"
style="stroke:#660000; fill:none;"/>
<path id="Line2" d="M110,110
L100,0"
style="stroke:#660000; fill:none;"/>
然后这段 JavaScript 代码:
var Line1 = document.getElementById("Line1");
var Line2 = document.getElementById("Line2");
//Add paths together
Line1.setAttribute('d', Line1.getAttribute('d') + ' ' + Line2.getAttribute('d'));
//Remove unnecessary second path
Line2.parentNode.removeChild(Line2);
将导致你有这样的单一路径:
<path id="Line1" d="M50,50
A30,30 0 0,1 35,20
L100,100 M110,110
L100,0"
style="stroke:#660000; fill:none;"/>
这里有一个 jsFiddle,它可以在 Firefox 4 中运行(需要 HTML5 解析器,以便您可以拥有内联 SVG)。
如果您的路径是相对的,那么您将必须在附加路径之间添加一些内容,以便第二个路径从正确的位置开始。
d
属性通常,您可以简单地连接多个
d
元素的 pathdata <path>
属性来获得复合路径 - 无论这些路径是使用相对、绝对还是命令。
不幸的是,您可能会遇到一些»不好的做法«使用
M
或m
作为可互换的启动命令。
事实上,每个 first
m
或 M
命令(在路径数据 d
属性中)都描述 absolute 坐标 - 因为没有没有前面的点。因此,大多数情况下,您可以将第一个 m
命令更改为大写并连接。
例外:小写的
m
命令引入了一行隐式相对的l
lineto命令。 (例如多边形/折线)。
m
命令开始的路径svg{
border:1px solid #ccc;
width:25%;
}
path{
fill:#555;
}
<p>Seperate paths</p>
<svg viewBox="0 0 50 10">
<path id="path1" d="m 20 0 l 10 0 l 0 10 l -10 0z" />
<path id="path2" d="m 40 0 l 10 0 l 0 10 l -10 0z" />
<path id="path3" d="m 0 0 l 10 0 l 0 10 l -10 0z" />
</svg>
<p>Merged paths</p>
<svg viewBox="0 0 50 10">
<path id="pathConcat"
d="
m 20 0 l 10 0 l 0 10 l -10 0z
m 40 0 l 10 0 l 0 10 l -10 0z
m 0 0 l 10 0 l 0 10 l -10 0z
" />
</svg>
<p>Merged paths - fixed</p>
<svg viewBox="0 0 50 10">
<path id="pathConcat"
d="
M 20 0 l 10 0 l 0 10 l -10 0z
M 40 0 l 10 0 l 0 10 l -10 0z
M 0 0 l 10 0 l 0 10 l -10 0z
" />
</svg>
修复:只需将每个起始
m
替换为绝对 M
m
相邻线段的命令例外情况是
m
命令后跟坐标 – 用作后续 l
(相对行号)的简写。 (另请参阅 w3c 规范。)
svg{
border:1px solid #ccc;
width:25%;
}
path{
fill:#555;
}
<p>Seperate paths</p>
<svg viewBox="0 0 50 10">
<path id="path1" d="m 20 0 10 0 0 10 -10 0z" />
<path id="path2" d="m 40 0 10 0 0 10 -10 0z" />
<path id="path3" d="m 0 0 10 0 0 10 -10 0z" />
</svg>
<p>Merged paths</p>
<svg viewBox="0 0 50 10">
<path id="pathConcat"
d="
m 20 0 10 0 0 10 -10 0z
m 40 0 10 0 0 10 -10 0z
m 0 0 10 0 0 10 -10 0z
" />
</svg>
<p>Merged paths - fixed</p>
<svg viewBox="0 0 50 10">
<path id="pathConcat"
d="
m 20 0 10 0 0 10 -10 0z
M 40 0 l 10 0 0 10 -10 0z
M 0 0 l 10 0 0 10 -10 0z
" />
</svg>
修复:插入
l
命令
<path d="m 20 0 10 0 0 10 -10 0z" />
等于
<path d="M 20 0 l 10 0 l 0 10 l -10 0z" />
或
<path d="M 20 0 l 10 0 0 10 -10 0z" />
m
修复伪相对
getPathData()
目前仍是草案,主要浏览器本身不支持。
不过你可以使用 Jarek Foksa 的 polyfill。.
getPathData()
将返回命令对象数组并标准化
重复这样的命令:
[
{type: 'm', values:[20, 0] },
{type: 'l', values:[10, 0]},
{type: 'l', values:[0, 10]},
{type: 'l', values:[-10, 0]}
]
function concatSimple(){
let d1= path1.getAttribute('d')
let d2= path2.getAttribute('d')
let d3= path3.getAttribute('d')
pathConcat.setAttribute('d', d1+d2)
}
function concatPathData(){
let pathData1= fixFirstM(path1.getPathData());
let pathData2= fixFirstM(path2.getPathData());
let pathData3= fixFirstM(path3.getPathData());
let pathDataConcat = pathData1.concat(pathData2).concat(pathData3);
pathConcat.setPathData(pathDataConcat);
}
// change first m to absolute M
function fixFirstM(pathData){
pathData[0].type='M';
return pathData;
}
svg{
border:1px solid #ccc;
width:25%;
}
path{
fill:#555;
}
<p><button onclick="concatSimple()">concat d simple</button>
<button onclick="concatPathData()">concat d pathData</button>
</p>
<svg viewBox="0 0 50 10">
<path id="path1" d="m 20 0 10 0 0 10 -10 0z" />
<path id="path2" d="m 40 0 10 0 0 10 -10 0z" />
<path id="path3" d="m 0 0 10 0 0 10 -10 0z" />
</svg>
<svg viewBox="0 0 50 10">
<path id="pathConcat" d="" />
</svg>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/path-data-polyfill.min.js"></script>
由于隐式 linetos 已转换为显式
l
命令,我们可以将第一个 moveto 更改为 M
pathData[0].type='M';
m
命令(如果它们实际上是相对的):l
命令的简写(如 m 20 0 10 0 0 10 -10 0z
)如果您需要合并形状 - paper.js 有一些强大的路径操作,如合并、减去等。
此处解释:“将两个基于贝塞尔曲线的形状合并为一个以创建新的轮廓”