web-dev-qa-db-fra.com

Convertir le polygone SVG en chemin

J'ai un fichier SVG assez volumineux de subdivisions administratives avec lequel je dois travailler dans Raphael.JS (il a 600 polygones et pèse 1,2 Mo).

Maintenant, je dois convertir ces polygones en chemins pour que cela fonctionne à Raphael. Le grand outil poly2path le fait, mais il ne prend en charge aucune commande batch, de sorte que la position de chaque polygone par rapport aux autres est perdue.

Connaissez-vous un outil pour convertir des polygones SVG en chemins? (J'ai également le fichier AI qui a été utilisé pour exporter le SVG).

Merci beaucoup

23
nkb
  1. Ouvrez votre SVG dans un navigateur Web.
  2. Exécutez ce code:

    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. À l'aide des outils de développement (ou Firebug) du navigateur, utilisez "Copier au format HTML" (ou Copier SVG) sur l'élément pour obtenir la source modifiée dans le presse-papiers.

  4. Collez dans un nouveau fichier et profitez-en.

J'ai une démonstration de la méthode ci-dessus (légèrement modifiée) sur mon site Web:
http://phrogz.net/svg/convert_polys_to_paths.svg

Il y a deux méthodes utilisées sur cette page; l'un (comme ci-dessus) utilise des techniques basées sur des chaînes pour obtenir et définir les points; l'autre utilise le SVG DOM pour accéder aux points et définir les commandes de chemin.


Comme indiqué par @Interactive dans les commentaires, vous pouvez le faire via des transformations de texte uniquement en:

  1. Convertir tout <polyline et <polygon à <path
  2. Change tout points=" à d="M
  3. Pour tous les éléments qui étaient <polygon>, vous devez ajouter z comme dernier caractère de l'attribut d pour connecter le dernier point au premier. Par exemple:

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

    devient

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

Ce "hack" fonctionne parce que les spécifications déclarent qu'une commande moveto (M ou m) suivie de plusieurs coordonnées est légale, avec toutes les coordonnées après la première interprétée comme des commandes lineto.

74
Phrogz

Tout copier à partir des outils de développement semble assez gênant. Vous pouvez utiliser un XSLT pour transformer des polygones et des polylignes en chemins:

<?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>

Tous les attributs des éléments de polygone/polyligne seront reportés sur l'élément de chemin. Cela convient également au traitement par lots. Vous pouvez l'exécuter en utilisant n'importe quel processeur XSLT (Saxon, Xalan, xsltproc, Altova ...) ou même dans le navigateur, en utilisant l'objet XSLTProcessor, comme:

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

(Question similaire: Exemples de polygones dessinés par chemin vs polygone en SVG )

4
Thomas W

Une réponse clicky-bunty:

  1. ouvrir le svg dans l'éditeur de graphiques vectoriels inkscape
  2. sélectionner tous les objets (ctrl-a)
  3. dans le menu déroulant, pointez "chemin" sélectionnez la première entrée "objet vers chemin" (shift-ctrl-c)
  4. enregistrez le svg et vérifiez les propriétés du chemin

Peut-être pas une réponse appropriée (car avec des fichiers volumineux, le programme a besoin de temps).

3
jaminka evening

Petite correction pour l'enregistrement des attributs de polygone id, fill et stroke

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