web-dev-qa-db-fra.com

Incorporation de SVG externe dans HTML pour la manipulation de JavaScript

J'ai une image SVG, montrant les régions géographiques. http://upload.wikimedia.org/wikipedia/commons/7/71/Nederland_gemeenten_2009.svg

Je souhaite afficher l'image SVG sur une page Web et utiliser une combinaison de JavaScript et CSS pour interagir avec l'image. (c.-à-d. détecter les clics sur une région, définir une couleur d'arrière-plan différente pour une région).

Je sais que cette question est posée plusieurs fois sur StackOverflow, mais je ne trouve pas d'exemple de code complet sur lequel travailler. Toutes les recommandations sur les packages JavaScript, comme jQuery, ou les plug-ins sont les bienvenues.

34
Gerrit

Ma compréhension de la question est qu'il y a différents aspects à résoudre:

  1. Comment préparer l'image pour l'interaction
  2. Comment intégrer l'image dans la page
  3. Comment utiliser CSS avec SVG
  4. Comment utiliser JavaScript pour l'interaction

Préparation de l'image

Tout d'abord, je recommanderais de nettoyer l'image. Inkscape laisse là toutes sortes de choses dont vous n'avez pas besoin, qui incluent des éléments et des attributs dans les espaces de noms sodipodi: Et inkscape: Ainsi que des attributs de style répétitifs et/ou redondants. Vous n'avez pas have pour supprimer cela, mais cela vous fait gagner du temps de bande passante/chargement, et si vous voulez travailler avec la correspondance CSS, que les attributs de style sont sur votre chemin.

Dans votre fichier d'exemple, vous avez 472 fois le même attribut de style. Supprimez-les tous et créez une règle CSS équivalente une fois.

Vous pouvez également ajouter des informations sur les municipalités au balisage. Vous pourriez par exemple changer les identifiants de chaque chemin représentant une municipalité selon son nom. Vous pouvez également utiliser un attribut data-* À cet effet. Ce dernier a l'avantage de pouvoir utiliser des espaces. Voir ci-dessous pour savoir comment cela est utile pour l'interaction, en particulier avec CSS.

Incorporation de l'image

Je recommanderais d'utiliser le SVG en ligne, surtout si vous souhaitez interagir avec CSS/JavaScript. Cela signifie que vous ajoutez simplement le balisage SVG à votre code HTML, ou vous le chargez et l'insérez à l'aide d'Ajax. Ce dernier a l'avantage que la page environnante se charge plus rapidement et se sent plus réactive.

Un exemple d'un élément SVG en ligne:

<div id="svgContainer">
  <!-- This is an HTML div, and inside goes the SVG -->
  <svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
    <circle r="50" cx="50" cy="50" fill="green"/>
  </svg>
</div>

Un exemple simplifié de chargement de SVG à l'aide d'Ajax:

xhr = new XMLHttpRequest();
xhr.open("GET","my.svg",false);
// Following line is just to be on the safe side;
// not needed if your server delivers SVG with correct MIME type
xhr.overrideMimeType("image/svg+xml");
xhr.send("");
document.getElementById("svgContainer")
  .appendChild(xhr.responseXML.documentElement);

Comment utiliser CSS

SVG peut être stylé comme HTML. Bien sûr, SVG possède son propre ensemble de propriétés, comme fill-opacity Ou stroke-dasharray Et ne prend pas en charge beaucoup de propriétés HTML, comme margin, position ou similaires. Mais les mécanismes de sélection sont identiques à 100%.

Vous pouvez mélanger le CSS pour votre SVG en ligne avec le CSS pour votre HTML, soit à l'intérieur d'un élément <style> Soit dans un fichier CSS externe. Vous pouvez également utiliser l'élément <style> À l'intérieur du code SVG et des attributs style.

En supposant que vous avez donné à vos éléments SVG des ID ou des attributs data-* Significatifs, deux façons de mettre en évidence les municipalités à l'aide de CSS seraient:

#Bronckhorst, #Laarbeek {fill:red}

ou

*[data-gemeente=Bronckhorst], *[data-gemeente=Laarbeek] {fill:red}

Ou, bien sûr, vous pouvez modifier les attributs de style des éléments respectifs. Les propriétés sont également prises en charge comme attribut, c'est-à-dire que style="stroke-width:2" Peut également être spécifié comme stroke-width="2". Si la même propriété est définie en utilisant à la fois un attribut et CSS (en utilisant l'attribut style, un élément de style ou une feuille de style externe), le CSS remplace l'attribut.

Interaction JavaScript

Il n'y a fondamentalement aucune différence entre HTML et SVG en ce qui concerne l'interaction JavaScript, au moins tant que vous utilisez le DOM Vanilla ordinaire. Cela signifie que les fonctionnalités spécifiques au HTML comme innerHTML ne sont pas prises en charge dans SVG (c'est-à-dire qu'il n'y a pas de innerSVG). Mais SVG possède son propre ensemble graphique de méthodes DOM spécifiques ( voir les spécifications du W3C ).

Une chose à savoir est le travail avec les espaces de noms. Tous les éléments SVG doivent se trouver dans l'espace de noms SVG, et lors de leur création à l'aide de JavaScript, createElementNS() doit être utilisé à la place de createElement():

var use = document.createElementNS("http://www.w3.org/2000/svg","use")

De même, les attributs dans l'espace de noms XLink (à savoir xlink:href) Doivent être manipulés en utilisant setAttributeNS() au lieu de setAttribute():

use.setAttributeNS("http://www.w3.org/1999/xlink","href","#foo")

Comme des bibliothèques comme jQuery s'appuient en partie sur des fonctionnalités spécifiques au HTML, il est plus sûr de les éviter lors de la manipulation de SVG. Il existe également des bibliothèques spécifiques à SVG comme Raphaël et D3.js qui peuvent être utiles à des fins spécifiques et valent le détour. Raphaël est particulièrement utile pour être compatible avec les versions 6 à 8 d'Internet Explorer pré-HTML5, qui ne prennent pas en charge SVG. Cependant, si je comprends bien, il ne convient vraiment que pour générer des graphiques entièrement en JavaScript plutôt que de travailler avec des graphiques existants, car il s'agit d'une couche d'abstraction au-dessus de SVG. D3.js serait plus adapté pour des applications comme la vôtre si vous n'êtes pas satisfait du DOM ordinaire (et, honnêtement, je le fais de l'injustice lorsque je l'appelle simplement une bibliothèque spécifique SVG, car c'est plus).

Vous pouvez utiliser onclick et des attributs similaires et DOM addEventListener() standard. Un exemple très simple d'utilisation d'événements JavaScript serait d'ajouter un écouteur d'événements à l'élément <svg> Qui signale le nom d'une municipalité sur laquelle un utilisateur a cliqué:

document.getElementsByTagName("svg")[0]
  .addEventListener("click",function(evt){
    alert(evt.target.getAttribute("data-gemeente"))
  },
  false)

Note: Toopltips Le même effet que vous obtenez en utilisant l'attribut title en HTML peut être obtenu en utilisant le <title> élément en SVG. Il suffit de mettre un élément <title> À l'intérieur d'un élément SVG et au survol, vous voyez une info-bulle avec le contenu de l'élément <title>.

<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
  <rect width="100" height="100">
    <title>test</title>
  </rect>
</svg>
88
Thomas W

Juste pour mémoire (sachant que cela arrive un an en retard), j'ai trouvé SnapSVG idéal pour la manipulation de SVG. Le même gars qui était derrière Raphaël:

http://snapsvg.io

8
droid001