我试图从 SVG 对象中提取所有线条,以便可以通过特殊的光栅器渲染它们,但事实证明这比我想象的要复杂得多。
主要挑战是:
svg
<line>
和<polyline>
元素有时可以包含在<defs>
中组,由元素呈现。这些需要展平。<path>
元素还需要转换为线元素。我很乐意扔掉花哨的曲线,只坚持直线。
是否有一种简单的方法可以做到这一点,或者是否有一些已经存在的代码可以避免重新发明轮子?我正在使用 Javascript 工作。
谢谢!
最佳答案
首先是第二点:
将弯曲路径转变为直线路径:
此时,它不会将其转换为 <line>
元素,但这样做应该不会太困难,而且我不确定您是否真的需要这个。
function simplifyPathes(svg) {
var pathes = svg.querySelectorAll('path');
for (i = 0; i < pathes.length; i++) {
for (var j = 0; j < pathes[i].pathSegList.numberOfItems; j++) {
var segment = pathes[i].pathSegList.getItem(j);
if (segment.pathSegType > 4) {
if (segment.pathSegType & 1) {
var newSeg = pathes[i].createSVGPathSegLinetoRel(segment.x, segment.y);
} else {
var newSeg = pathes[i].createSVGPathSegLinetoAbs(segment.x, segment.y);
}
pathes[i].pathSegList.replaceItem(newSeg, j);
}
}
}
}
setTimeout(function(){simplifyPathes(document.querySelector('svg'))}, 1500);
<svg width="600" height="300" viewBox="0 0 600 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="path" fill="none" stroke="#000000" stroke-miterlimit="10" d="M286,81c-70.7,14-134.3-57.3-91.3-2.7s145,74.7,53,74.3 C155.7,152.3,150,16,164.3,93c14.3,77-33.7,68.7,53,87s-23.7,31.7-123,6.3-52,86-150,0" />
</defs>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M161,88.7c-3.3,44-58.4-5.7-58.4-5.7s-41-31,49.4-31.7 c90.3-0.7,86-61.3,83.7,2.7c-2.3,64,54.3,57.3-19.3,71.6S-27,47.7,89,110.7s107.7,152.7,106.7,65.7" />
<use xlink:href="#path" transform="translate(75, 25)" />
</svg>
可能有更好的方法,但我还没有。
Some readings here
您可能想将它与一些库结合起来,例如 simplify.js 。
现在,问题的第一部分。
我假设如果 <use>
元素是一个问题,那是因为 Gecko's restrictive rules on external resources in svg Images .
如果不是这种情况,我很好奇为什么需要“扁平化”。
我写了一个可怕的 hack,它可能会向您展示一种解决方法。
function cloneUses(svg) {
var uses = svg.querySelectorAll('use')
for (i = 0; i < uses.length; i++) {
var elem = uses[i],
id = elem.getAttributeNS('http://www.w3.org/1999/xlink', 'href').substring(1),
c = svg.getElementById(id).cloneNode(true),
b = elem.transform.baseVal,
a = elem.attributes;
if(b.length>1){
b.consolidate();
c.transform.baseVal.appendItem(b.getItem(0));
c.transform.baseVal.consolidate();
}
for (j = 0; j < a.length; j++) {
if (a[j].value !== ('#' + id) && a[j].value !== "transform") {
c.setAttribute(a[j].name, a[j].value);
}
}
elem.parentNode.insertBefore(c, elem);
elem.parentNode.removeChild(elem);
}
}
setTimeout(function(){cloneUses(document.querySelector('svg'))}, 1500);
<svg width="600" height="300" viewBox="0 0 600 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<line id="line" stroke="black" x1="72" y1="120" x2="25" y2="25" />
<path id="path" fill="none" stroke="#000000" stroke-miterlimit="10" d="M286,81c-70.7,14-134.3-57.3-91.3-2.7s145,74.7,53,74.3 C155.7,152.3,150,16,164.3,93c14.3,77-33.7,68.7,53,87s-23.7,31.7-123,6.3-52,86-150,0" />
</defs>
<use xlink:href="#path" transform="translate(75, 25)" />
<use xlink:href="#line" transform="translate(125, 0)" />
</svg>
Ps:我让你想办法改造<circle>
进入<line>
靠你自己。
关于javascript - 在 Javascript 中从 SVG 对象中提取所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29044631/