将SVG多边形转换为路径

35

我有一个相当大的行政区划SVG文件,其中包含600个多边形,大小为1.2 Mb。现在,我需要将这些多边形转换为path,以便在Raphael.JS中使用。有一个非常好用的poly2path工具可以做到这一点,但它不支持任何批量命令,因此每个多边形相对于其他多边形的位置都会丢失。

你知道有没有工具可以将SVG多边形转换为路径?(我还有用于导出SVG的AI文件)。

非常感谢。


2
如果您再次访问 @nkb,请接受您喜欢的答案。 - halfer
5个回答

103
  1. 在网页浏览器中打开你的SVG文件。

  2. 运行以下代码:

 var polys = document.querySelectorAll('polygon,polyline');
 [].forEach.call(polys,convertPolyToPath);

 function convertPolyToPath(poly){
   var svgNS = poly.ownerSVGElement.namespaceURI;
   var path = document.createElementNS(svgNS,'path');
   var pathdata = 'M '+poly.getAttribute('points');
   if (poly.tagName=='polygon') pathdata+='z';
   path.setAttribute('d',pathdata);
   poly.getAttributeNames().forEach(function(name){
     if(name !== 'points')
       path.setAttribute(name, poly.getAttribute(name))
   })
   poly.parentNode.replaceChild(path,poly);
 }
  • 使用浏览器的开发工具(或者Firebug),在元素上使用“复制为HTML”(或者复制SVG)来将修改后的源代码复制到剪贴板中。

  • 将其粘贴到一个新文件中,然后享受它。

  • 我在我的网站上演示了上述方法(稍作修改):
    http://phrogz.net/svg/convert_polys_to_paths.svg

    该页面上有两种方法;一种(像上面的方法)使用基于字符串的技术来获取和设置点;另一种使用SVG DOM来访问点并设置路径命令。


    正如@Interactive在评论中指出的那样,您可以通过纯文本转换来完成以下操作:

    1. 将所有的<polyline <polygon 转换为<path

    2. 将所有的points="改为d="M

    3. 对于任何被<polygon>包含的元素,你需要在d属性的最后一个字符添加z以将最后一个点连接到第一个点。例如:

       <polygon points="1,2 3,-4 5,6"/> 
      

      变成

       <path d="M1,2 3,-4 5,6z"/> 
      

    这种“技巧”之所以有效,是因为规范声明,一个使用多个坐标的moveto命令(Mm)是合法的,除第一个坐标外后面所有的坐标都会被解释为lineto命令。


    这在所有浏览器中与Raphael很好地配合使用(甚至是IE7-8),但在IE9中不起作用。 Raphael根据此函数不绘制路径。 你有任何想法为什么吗? - Roman
    请使用SVG标签和重现案例将此内容作为问题提出,谢谢。 - Phrogz
    @Interactive 将其放置在 SVG 文件底部的 <script> 块中,或者打开开发者工具并将其粘贴到控制台中。 - Phrogz
    重要提示:我发现了一个问题。这个方法对我有效,但是需要注意的是:请将所有的<polyline替换为<path,并将points="替换为d="M。具体内容可以在此链接中找到:https://gist.github.com/andytlr/9283541 - Interactive
    1
    @Interactive 这是一项很棒的技巧,而且它也是有效的。moveto 命令的规范明确指出,除第一对坐标外的其他坐标将被视为隐式的 lineto 命令。我会编辑我的答案并添加上述内容。 - Phrogz

    6
    一个简单易懂的答案:
    1. 使用inkscape矢量图形编辑器打开svg文件
    2. 选择所有物体(ctrl-a)
    3. 在下拉菜单中选择“路径”,然后选第一个选项“对象转路径”(shift-ctrl-c)
    4. 保存svg文件并查看路径属性
    提示:对于大文件可能需要一些时间,这个答案可能不是最合适的。

    4

    对多边形ID、填充和描边属性进行了小修复

    var polys = document.querySelectorAll('polygon,polyline');
    [].forEach.call(polys,convertPolyToPath);
    
    function convertPolyToPath(poly){
      var svgNS = poly.ownerSVGElement.namespaceURI;
      var path = document.createElementNS(svgNS,'path');
      var points = poly.getAttribute('points').split(/\s+|,/);
      var x0=points.shift(), y0=points.shift();
      var pathdata = 'M'+x0+','+y0+'L'+points.join(' ');
      if (poly.tagName=='polygon') pathdata+='z';
      path.setAttribute('id',poly.getAttribute('id'));
      path.setAttribute('fill',poly.getAttribute('fill'));
      path.setAttribute('stroke',poly.getAttribute('stroke'));
      path.setAttribute('d',pathdata);
    
      poly.parentNode.replaceChild(path,poly);
    }
    

    3
    还有其他一些可能会感兴趣的属性,例如class、style、transform、clip-path、color、onclick、display、fill-rule、opacity等。 - Thomas W

    4

    从开发者工具中复制所有内容似乎非常不方便。您可以使用XSLT将多边形和折线转换为路径:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" exclude-result-prefixes="svg"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns="http://www.w3.org/2000/svg"
        xmlns:svg="http://www.w3.org/2000/svg">
    
      <!-- Identity transform: Copy everything 
           (except for polygon/polyline, handled below) -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <!-- Turn polygons/polylines into paths, 
           copy all attributes and content 
           (except for @points: Will be matched
           by template below) -->
      <xsl:template match="svg:polygon|svg:polyline">
        <path>
          <xsl:apply-templates select="@*|node()"/>
        </path>
      </xsl:template>
    
      <!-- Turn the points attribute into a d attribute -->
      <xsl:template match="@points">
        <xsl:attribute name="d">
          <xsl:value-of select="concat('M',.)"/>
          <!-- If we have a polygon, we need to make 
               this a closed path by appending "z" -->
          <xsl:if test="parent::svg:polygon">
            <xsl:value-of select="'z'"/>
          </xsl:if>
        </xsl:attribute>
      </xsl:template>
    </xsl:stylesheet>
    

    多边形/折线元素的任何属性都将传递到路径元素。这也适用于批处理。您可以使用任何XSLT处理器(Saxon、Xalan、xsltproc、Altova...)运行此操作,甚至可以在浏览器中使用XSLTProcessor对象,例如:

    var xsltProcessor = new XSLTProcessor();
    xsltProcessor.importStylesheet(stylesheet);
    var transformedSVG = xsltProcessor.transformToFragment(svgDocument).firstChild
    

    (类似的问题:SVG中通过路径和多边形绘制的多边形示例


    0
    在@halfer的解决方案基础上进行改进。如果您有内部CSS并希望保留类名,可以稍微修改如下:

    var polys = document.querySelectorAll('polygon,polyline');
    [].forEach.call(polys,convertPolyToPath);
    
    function convertPolyToPath(poly){
      var svgNS = poly.ownerSVGElement.namespaceURI;
      var path = document.createElementNS(svgNS,'path');
      var pathClass = poly.getAttribute('class');
      var points = poly.getAttribute('points').split(/\s+|,/);
      var x0=points.shift(), y0=points.shift();
      var pathdata = 'M'+x0+','+y0+'L'+points.join(' ');
      if (poly.tagName=='polygon') pathdata+='z';
      path.setAttribute('id',poly.getAttribute('id'));
      path.setAttribute('class', pathClass);
      path.setAttribute('d',pathdata);
    
      poly.parentNode.replaceChild(path,poly);
    }


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