是否有一种方法可以使用Javascript合并两个路径元素(svg)
Is there a way to merge two path elements (svg) using Javascript?
我使用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
属性
通常,您可以将多个<path>
元素的pathdata d
属性连接起来,得到一个组合路径。
不幸的是,您可能会遇到一些»不良做法«使用M
或m
作为可互换的命令。
关于M
或m
的常见误解:
-
M
(moveto)可以是绝对的或相对的。
不像z
(closepath)命令(小写/大写-不重要)。
相对m
命令可用于复合路径,例如内部"hole"字母"o";参考前一个命令的结束坐标。 - 事实上,每个第一个
m
或M
命令都使用绝对坐标-因为没有前面的点。 - 但是,
M
的第一个命令可以是大写或小写——这无关紧要
(怪规格) -
例外:小写的
m
命令引入了一行隐式的相对l
lineto命令。(但你也可以/应该避免这种情况)
示例1:以(不必要的)relative m
command
开头的路径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
示例2:相邻行
的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" />
示例3:通过getPathData()
修复伪相对m
命令
目前仍然是一个草案,不支持原生的主要浏览器。
但是你可以使用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/path-data-polyfill@1.0.4/path-data-polyfill.min.js"></script>
要修复第一个相对m
,我们可以通过更改第一个命令类型进行转换
pathData[0].type='M';
建议:只使用相对的m
命令,如果它们实际上是相对的:
- 如果您需要以下
l
命令的简写(如m 20 0 10 0 0 10 -10 0z
) 复合路径中的相对(子路径)起始点 - -如字母"o"
实际合并形状:删除重叠的形状
如果你需要合并形状- paper.js有一些强大的路径操作,如统一,减去等
相关文章:
- 如何使用javascript合并两个对象数组
- 别名或以其他方式合并两个具有不同名称的相同对象原型
- 如何在javascript中合并两个对象数组
- JavaScript - 合并两个对象数组并根据属性值删除重复数据
- 如何使用jQuery合并两个json对象
- 合并两个剪辑区域-詹姆斯·邦德枪管
- 合并两个对象而不覆盖
- 在kibana3/elastic.js中合并两个过滤器
- 合并两个嵌套的JSON数组
- 合并两个Javascript数组,一次合并三个元素
- 有没有一个lodash函数可以合并两个对象并删除其中一个对象的属性(如果它们没有)'不存在于另一个中
- 是否有任何功能可以合并两个JSON数据集并替换旧信息?(节点.JS)
- Angularjs合并两个忽略null和缺失值的对象
- 在 JavaScript 中合并两个对象
- 如何在培根中合并两个属性.js
- 合并两个对象数组,同时对特定键求和
- 在 javascript 中合并两个对象
- Javascript:根据其他字段合并两个JSON
- 合并两个 JavaScript 对象而不覆盖
- 合并两个节点列表而不重复