javascript - 在 Javascript 中从 SVG 对象中提取所有行

标签 javascript jquery svg

我试图从 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>
通过浏览器的检查器查看 svg

Ps:我让你想办法改造<circle>进入<line>靠你自己。

关于javascript - 在 Javascript 中从 SVG 对象中提取所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29044631/

相关文章:

javascript - 使用 vanillaJS 无限绘制/取消绘制 SVG 路径循环

html - SVG 图标包含在页面中时看起来有所不同

javascript - XMLHttpRequest JS 图片加载

javascript - 具有 Websocket 连接的 Cloudfront

javascript - 使用 JavaScript 触发 happy.js 验证?

jquery - Kartik Select2 在附加 jquery 后不起作用

python - 在 Python 中将 SVG 转换为 PNG

javascript - 是否有相当于 Spring :bind for binding forms and data on the front end?

Javascript:为多个新对象()重用变量。不好的做法?

javascript - 如何在 Javascript 中访问 JSON 对象?