web-dev-qa-db-ja.com

SVGポリゴンをパスに変換する

Raphael.JSで使用する必要がある管理サブディビジョンのかなり大きなSVGファイルがあります(600のポリゴンと1.2 Mbのウェイトがあります)。

次に、これらのポリゴンをパスに変換して、ラファエルで機能するようにする必要があります。すばらしい poly2pathツール はそれを実行しますが、バッチコマンドをサポートしていないため、各ポリゴンの相対的な位置が失われます。

SVGポリゴンをパスに変換するツールを知っていますか? (SVGのエクスポートに使用したAIファイルもあります)。

どうもありがとう

23
nkb
  1. Webブラウザーで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.parentNode.replaceChild(path,poly);
    }
    
  3. ブラウザーの開発者ツール(またはFirebug)を使用して、要素で「HTMLとしてコピー」(またはSVGをコピー)を使用して、変更されたソースをクリップボードに取得します。

  4. 新しいファイルに貼り付けてお楽しみください。

私のウェブサイトに上記の方法のデモ(わずかに変更)があります。
http://phrogz.net/svg/convert_polys_to_paths.svg

そのページで使用されている2つの方法があります。 1つは(上記のように)文字列ベースの手法を使用してポイントを取得および設定します。もう1つは、ポイントへのアクセスとパスコマンドの設定にSVG DOMを使用します。


コメントの@Interactiveで述べられているように、次の方法でテキストのみの変換を介してこれを行うことができます。

  1. すべての<polylineおよび<polygon<pathに変換します
  2. すべてのpoints="d="Mに変更します
  3. <polygon>であった要素については、z属性の最後の文字としてdを追加して、最後のポイントを最初のポイントに接続する必要があります。例えば:

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

    なる

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

この「ハッキング」は、複数の座標が続くmovetoコマンド(Mまたはm)がすべての座標で正当であることを 仕様が宣言している であるため機能します。最初はlinetoコマンドとして解釈された後。

74
Phrogz

開発者ツールからすべてをコピーすることは、かなり不便なようです。 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>

ポリゴン/ポリライン要素の属性は、パス要素に引き継がれます。これはバッチ処理にも適しています。これは、次のようなXSLTProcessorオブジェクトを使用して、任意のXSLTプロセッサー(Saxon、Xalan、xsltproc、Altova ...)またはブラウザー内で実行できます。

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

(同様の質問: パスで描画されたポリゴンとSVGのポリゴンの例

4
Thomas W

クリック感のある答え:

  1. inkscapeベクトルグラフィックエディタでsvgを開きます
  2. すべてのオブジェクトを選択(Ctrl-A)
  3. ドロップダウンメニューポイント「パス」で最初のエントリ「パスへのオブジェクト」を選択(shift-ctrl-c)
  4. svgを保存し、パスのプロパティを確認する

適切な答えではない可能性があります(ファイルが大きい場合、プログラムには時間がかかるため)。

3
jaminka evening

ポリゴン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
boooch