SVG : un format d’image… dynamique !

SVG : un format d’image… dynamique !

Difficulté

php xml htmlcss

Le Scalable Vector Graphics ou SVG est un format d’image vectoriel, et se présente sous la forme d’un document xml.

Vectoriel, il est donc très léger. Par exemple, l’image sur laquelle nous allons travailler pèse 6Ko, contre 15ko pour sa version png et 66Ko pour sa version jpg.

A noter : la plupart des navigateurs supporte ce format depuis quelques années déjà.

Sa DTD est décrite par le W3C, et le document est en fait un XML avec des balises spécifiques.
Voyons un peu plus en détail son contenu :

1. La stucture du fichier SVG

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg height="194.881882" id="svg602" version="1.0" width="194.881882" x="0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0">
  <metadata>
    <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
        <dc:format>image/svg+xml</dc:format>
        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
        <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
        <dc:language>en</dc:language>
      </cc:Work>
      <cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
        <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
        <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
        <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
      </cc:License>
    </rdf:RDF>
  </metadata>
  <defs id="defs603">
    <marker id="ArrowEnd" markerHeight="3" markerUnits="strokeWidth" markerWidth="4" orient="auto" refX="0" refY="5" viewBox="0 0 10 10">
      <path d="M 0 0 L 10 5 L 0 10 L 0 0 z " id="path605" style="font-size:12;"/>
    </marker>
    <marker id="ArrowStart" markerHeight="3" markerUnits="strokeWidth" markerWidth="4" orient="auto" refX="10" refY="5" viewBox="0 0 10 10">
      <path d="M 10 0 L 0 5 L 10 10 L 10 0 z " id="path607" style="font-size:12;"/>
    </marker>
  </defs>
  <circle cx="1500" cy="50" r="40" style="fill:yellow;stroke:purple;stroke-width:2" />
  <rect width="300" height="100" style="fill:#FFF; stroke-width:1;stroke:#000;"/>
  <line x1="0" y1="0" x2="200" y2="200" style="stroke:#000;stroke-width:2"/>
  <g id="g609" transform="translate(-645.2025,-362.3907)">
      <path d="M 665.241 525.241 L 785.241 525.241 C 796.28 525.241 805.241 516.28 805.241 505.241 L 805.241 385.241 C 805.241 374.201 796.28 365.241 785.241 365.241 L 665.241 365.241 C 654.201 365.241 645.241 374.201 645.241 385.241 L 645.241 505.241 C 645.241 516.28 654.201 525.241 665.241 525.241 z " id="path610" style="stroke:#000000;"/>
      <path d="M 667.651 375.241 L 782.831 375.241 C 789.681 375.241 795.241 380.801 795.241 387.651 L 795.241 502.831 C 795.241 509.681 789.681 515.241 782.831 515.241 L 667.651 515.241 C 660.801 515.241 655.241 509.681 655.241 502.831 L 655.241 387.651 C 655.241 380.801 660.801 375.241 667.651 375.241 z " id="path611" style="fill:#ffffff;stroke:#000000;"/>
  </g>
</svg>

Nous voyons ici quelques balises utilisées :
- Les coordonnées de chaque point d’un tracé (balise <g>),
- Les formes (<rect>, <circle> ou <line>), respectivement un rectangle , un cercle et une ligne avec leurs attributs de position, de taille (width, r cx cy…)

L‘attribut  style permet de personnaliser le rendu, comme pour une balise xhtml classique fill pour la couleur de fond, stroke pour le contour, stroke-width pour l’épaisseur du contour…)

Nous allons voir qu’en couplant PHP et JQuery, nous pouvons modifier les couleurs de l’image SANS RECHARGER LA PAGE et sans Ajax.

Voila le rendu de ce que nous allons faire : au clic sur une couleur, on modifie la couleur correspondante dans l’image SVG :

2. L’affichage d’une image SVG en xhtml

Commençons par le fichier SVG, l’icône contenant les petits bonhommes et les bulles
Celui là a été trouvé sur le web ici.

Si vous le souhaitez ,vous pouvez les créer, par exemple avec Illustrator, le logiciel de dessin vectoriel par excellence.

Vous pouvez vous faire une idée de son contenu en le téléchargeant ici en cliquant droit et « enregistrer la cible sous », sinon, il vous l’affichera dans votre navigateur !
Vous pouvez maintenant l’éditer avec un éditeur de texte quelconque…

Pour pouvoir le modifier en utilisant des variables passées par l’url, nous allons en faire un fichier php, par exemple en le renommant icon_01.svg.php

Pour inclure ce SVG dans une page web, il suffit de l’intégrer grâce au code suivant :

<div id="img_svg">
	<object type="image/svg+xml" id="image" data="icon_01.svg.php" width="300px" height="300px"> 
	  Le navigateur ne supporte pas les fichiers SVG !   
	</object>
</div>

A noter : il est possible d’afficher un svg statique (icon1.svg) avec la balise <img>.
Un svg dynamique (icon.svg.php) comme le notre doit être inclus par la balise <object>.

3. Modifier un fichier SVG grâce au php

Les lignes qui nous intéressent sont au niveau des attributs style, notamment les propriétés fill et stroke.

Ici, on ne s’occupera que de la propriété stroke car l’image a été construite par des contours de tracé, sauf pour les têtes que nous ne traiterons pas.

Pour modifier les couleurs de chaque bonhomme et des bulles -soit 3 couleurs- , il suffira donc de modifier le code couleur hexadécimal de stroke, en passant la variable de la couleur choisie par l’url en GET.

Tout en haut de notre fichier icon_01.svg.php, nous aurons donc :

<?php
$couleur1="#000000";
$couleur2="#000000";
$couleur3="#000000";

if(isset($_GET['couleur1']))$couleur1=urldecode($_GET['couleur1']);
if(isset($_GET['couleur2']))$couleur2=urldecode($_GET['couleur2']);
if(isset($_GET['couleur3']))$couleur3=urldecode($_GET['couleur3']);
?>

On définit des 3 couleurs par défaut, puis on affecte les variables venant de l’URL à nos variables couleurs.

Pour la suite, on remplace les codes couleurs stroke du fichier par un simple echo en php, et le tour est joué !

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">  
<svg height="194.881882" id="svg602" version="1.0" width="194.881882" x="0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0">
  <metadata>
    <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <cc:Work rdf:about="">
        <dc:title>Chat Icon</dc:title>
        <dc:description>contact: hermann.schwarting@knackich.de</dc:description>
        <dc:subject>
          <rdf:Bag>
            <rdf:li>icon</rdf:li>
            <rdf:li/>
            <rdf:li>callout</rdf:li>
            <rdf:li>people</rdf:li>
            <rdf:li>smiley</rdf:li>
            <rdf:li>appicon</rdf:li>
          </rdf:Bag>
        </dc:subject>
        <dc:publisher>
          <cc:Agent rdf:about="http://www.openclipart.org">
            <dc:title>Hermann Schwarting</dc:title>
          </cc:Agent>
        </dc:publisher>
        <dc:creator>
          <cc:Agent>
            <dc:title>Hermann Schwarting</dc:title>
          </cc:Agent>
        </dc:creator>
        <dc:rights>
          <cc:Agent>
            <dc:title>Hermann Schwarting</dc:title>
          </cc:Agent>
        </dc:rights>
        <dc:date/>
        <dc:format>image/svg+xml</dc:format>
        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
        <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
        <dc:language>en</dc:language>
      </cc:Work>
      <cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
        <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
        <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
        <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
      </cc:License>
    </rdf:RDF>
  </metadata>
  <defs id="defs603">
    <marker id="ArrowEnd" markerHeight="3" markerUnits="strokeWidth" markerWidth="4" orient="auto" refX="0" refY="5" viewBox="0 0 10 10">
      <path d="M 0 0 L 10 5 L 0 10 L 0 0 z " id="path605" style="font-size:12;"/>
    </marker>
    <marker id="ArrowStart" markerHeight="3" markerUnits="strokeWidth" markerWidth="4" orient="auto" refX="10" refY="5" viewBox="0 0 10 10">
      <path d="M 10 0 L 0 5 L 10 10 L 10 0 z " id="path607" style="font-size:12;"/>
    </marker>
  </defs>
  <g id="g817" style="font-size:12;" transform="translate(17.12688,13.67897)">
    <g id="g609" transform="translate(-645.2025,-362.3907)">
      <path d="M 665.241 525.241 L 785.241 525.241 C 796.28 525.241 805.241 516.28 805.241 505.241 L 805.241 385.241 C 805.241 374.201 796.28 365.241 785.241 365.241 L 665.241 365.241 C 654.201 365.241 645.241 374.201 645.241 385.241 L 645.241 505.241 C 645.241 516.28 654.201 525.241 665.241 525.241 z " id="path610" style="stroke:#000000;"/>
      <path d="M 667.651 375.241 L 782.831 375.241 C 789.681 375.241 795.241 380.801 795.241 387.651 L 795.241 502.831 C 795.241 509.681 789.681 515.241 782.831 515.241 L 667.651 515.241 C 660.801 515.241 655.241 509.681 655.241 502.831 L 655.241 387.651 C 655.241 380.801 660.801 375.241 667.651 375.241 z " id="path611" style="fill:#ffffff;stroke:#000000;"/>
    </g>
    <path d="M 54.55351 64.91729 C 55.89751 59.68629 62.05751 49.63329 57.00751 49.51729 C 51.95751 49.40029 40.03851 49.51729 40.03851 49.51729 C 40.03851 49.51729 20.03851 49.51729 20.03851 36.18329 C 20.03851 22.85029 33.37151 22.85029 46.70551 22.85029 C 60.03851 22.85029 80.03851 22.85029 80.03851 36.18329 C 80.03851 49.51729 66.70551 49.51729 66.70551 49.51729 C 66.70551 49.51729 57.99451 59.77429 54.55351 64.91729 z " id="path621" style="fill:none;stroke:<?php echo $couleur1; ?>;stroke-width:2;"/>
    <path d="M 103.8845 73.12129 C 103.0535 66.02229 105.5605 65.53629 105.5605 65.53629 C 105.5605 65.53629 112.8905 65.53629 112.8905 65.53629 C 112.8905 65.53629 134.8795 65.53629 134.8795 50.87729 C 134.8795 36.21829 112.8905 36.21829 105.5605 36.21829 C 98.23051 36.21829 83.57151 36.21829 83.57151 50.87729 C 83.57151 65.53629 98.23051 65.53629 98.23051 65.53629 C 98.23051 65.53629 99.89751 66.55429 103.8845 73.12129 z " id="path622" style="fill:none;stroke:<?php echo $couleur1; ?>;stroke-width:2;"/>
    <g id="g649" transform="translate(-645.2025,-362.3907)">
      <path d="M 698.901 454.821 C 694.948 459.611 688.184 461.482 682.156 458.972 C 674.774 455.899 671.277 447.412 674.35 440.029 C 677.424 432.647 685.911 429.15 693.293 432.223 C 700.676 435.297 704.173 443.784 701.099 451.166 L 687.725 445.598 L 698.901 454.821 z " id="path650" style="stroke:#000000;"/>
      <path d="M 686.276 460.086 L 681.447 515.138 " id="path651" style="fill:none;stroke:<?php echo $couleur2; ?>;stroke-width:3;"/>
      <path d="M 654.887 490.026 L 672.272 469.261 L 699.315 470.71 L 711.871 498.719 L 725.875 480.851 L 733.119 481.334 " id="path652" style="fill:none;stroke:<?php echo $couleur2; ?>;stroke-width:3;"/>
    </g>
    <g id="g653" transform="translate(-645.2025,-362.3907)">
      <path d="M 750.953 458.469 C 747.84 453.243 748.257 446.395 752.461 441.553 C 757.704 435.514 766.861 434.869 772.899 440.111 C 778.937 445.354 779.583 454.511 774.34 460.549 C 769.098 466.587 759.941 467.233 753.903 461.99 L 763.401 451.051 L 750.953 458.469 z " id="path654" style="stroke:#000000;"/>
      <path d="M 764.025 465.398 L 777.064 515.138 " id="path655" style="fill:none;stroke:<?php echo $couleur3; ?>;stroke-width:3;"/>
      <path d="M 767.889 481.817 L 735.051 504.031 L 762.577 508.86 " id="path656" style="fill:none;stroke:<?php echo $couleur3; ?>;stroke-width:3;"/>
    </g>
  </g>
</svg>

Nous voyons ici qu’il y a 2 stroke pour les bulles, et 2 pour chaque corps de bonhomme.

Pour mieux cibler le tracé choisi, je vous conseille d’utiliser l’extension pour Firefox Firebug :

svg firebug

4. Une palette de couleur en html

Passons à notre fichier html. Je créée une palette de couleur avec un simple tableau.

<table cellpadding="0" cellspacing="1" id="couleur">
    <tr id="id1">
        <td style="width:80px;">Bla Bla</td>    
      <td  style="background-color: #000000;"></td>
      <td  style="background-color: #C0C0C0;" ></td>
      <td  style="background-color: #ff0000;" ></td>
      <td  style="background-color: #ff9900;" ></td>
      <td  style="background-color: #ffcc66;" ></td>
      <td  style="background-color: #ffff00;" ></td>
      <td  style="background-color: #33ff33;" ></td>
      <td  style="background-color: #66cccc;" ></td>
      <td  style="background-color: #33ccff;" ></td>
      <td  style="background-color: #6666cc;" ></td>
      <td  style="background-color: #cc66cc;" ></td>
    </tr>
    <tr id="id2">
        <td> Marge</td>    
        <td  style="background-color: #000000;"></td>
        <td  style="background-color: #C0C0C0;" ></td>
        <td  style="background-color: #ff0000;" ></td>
        <td  style="background-color: #ff9900;" ></td>
        <td  style="background-color: #ffcc66;" ></td>
        <td  style="background-color: #ffff00;" ></td>
        <td  style="background-color: #33ff33;" ></td>
        <td  style="background-color: #66cccc;" ></td>
        <td  style="background-color: #33ccff;" ></td>
        <td  style="background-color: #6666cc;" ></td>
        <td  style="background-color: #cc66cc;" ></td>
    </tr>
    <tr id="id3">
        <td> Homer</td>    
        <td  style="background-color: #000000;"></td>
        <td  style="background-color: #C0C0C0;" ></td>
        <td  style="background-color: #ff0000;" ></td>
        <td  style="background-color: #ff9900;" ></td>
        <td  style="background-color: #ffcc66;" ></td>
        <td  style="background-color: #ffff00;" ></td>
        <td  style="background-color: #33ff33;" ></td>
        <td  style="background-color: #66cccc;" ></td>
        <td  style="background-color: #33ccff;" ></td>
        <td  style="background-color: #6666cc;" ></td>
        <td  style="background-color: #cc66cc;" ></td>
    </tr>
</table>

Ici, on utilise la valeur bakground-color de l’attribut style de la cellule pour récupérer le code couleur choisi.
A noter la classe active affectée aux cellules noires, les couleurs par défaut, et qui sera affectée à la cellule de tableau cliquée.

Voici les quelques css correspondants :

#couleur{
	float:left; 
	margin-top:40px; 
	margin-left:5px; 
	border-collapse:collapse;
}	
td{
	width:24px;
	height:39px;
	cursor:pointer;
	border: 1px solid #CCC;
}

#img_svg{margin-left:400px;}

5. Un code couleur récupéré grâce à JQuery

JQuery va nous aider à faire le reste:

<script type="text/javascript">
// <![CDATA[
$(function(){

//Affection de la classe "active" à la cellule cliquée
$("#id1 td").click(function(){
	$("#id1 td").removeClass("active");
  $(this).addClass("active");
});
$("#id2 td").click(function(){
	$("#id2 td").removeClass("active");
  $(this).addClass("active");
});
$("#id3 td").click(function(){
	$("#id3 td").removeClass("active");
  $(this).addClass("active");
});

//On recharge le svg
 $("#couleur td").click(function(){ 
     var newObjElement = '<object type="image/svg+xml" id="image" data="icon_01.svg.php?couleur1='+encodeURIComponent($("#id1 td.active").css('background-color'))+'&couleur2='+encodeURIComponent($("#id2 td.active").css('background-color'))+'&couleur3='+encodeURIComponent($("#id3 td.active").css('background-color'))+'" width="300px" height="300px"><embed src="icon_01.svg.php?couleur1='+encodeURIComponent($("#id1 td.active").css('background-color'))+'&&couleur2='+encodeURIComponent($("#id2 td.active").css('background-color'))+'&couleur3='+encodeURIComponent($("#id3 td.active").css('background-color'))+'" width="300px" height="300px" type="image/svg+xml" />Le navigateur ne supporte pas les fichiers SVG !</object>';
    $('#img_svg').html(newObjElement);
});

});
// ]]>
</script>

Quelques explications :
- Au clic sur une couleur, la classe de la cellule devient active,après avoir supprimée la classe active précédente de la même ligne.
- On récupère les valeurs bakground-color de l’attribut style de  chacune des 3 cellules de classe active.
- La valeur est encodée, puis passée en argument à l’url du fichier svg.php
- Le svg va donc se recharger pour se positionner… A la place de l’ancien… grâce à la méthode html
A chaque clic, on déclenche donc le « rechargement » du svg (attention, ce n’est pas de l’ajax !) en le « poussant ».

Plutôt sympa, non? ;)

Les commentaires sont fermés.