Carte interactive en SVG avec tooltip

Rajouter des liens

Une fois toutes les régions insérées dans l’image SVG on obtient une carte dont les régions changent de couleur au survol de la souris, mais ces régions ne sont pas cliquables.

Pour insérer des liens dans un document SVG, il faut utiliser le namespace XML XLink. Pour utiliser ce namespace dans votre image, la balise d’ouverture devient :

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="432" height="463" viewbox="0 0 432 463" id="map">

En SVG, un lien se créé avec la balise <a>. La principale différence avec le HTML est que les attributs de cette balise doivent être préfixés avec ‘xlink:‘. Comme avec le HTML,  la page cible se définit avec l’attribut ‘href‘, mais à la place de ‘target‘ il faut utiliser l’attribut ‘show‘.

En plaçant alors nos régions dans leur lien respectif, pour chaque région, on obtient :

<a xlink:href="https://fr.wikipedia.org/wiki/%C3%8Ele-de-France" xlink:show="new">
<polygon points="263,127 263,135 253,136 247,146 234,143 230,135 218,135 205,122 204,113 202,110 203,99 210,97 222,94 228,98 233,95 238,101 257,103 257,99 266,112 268,123 263,127" data-tooltip="Île-de-France"  />
</a>

Rajouter un tooltip

Pour rajouter un tooltip à ma carte, je me suis inspiré du script présenté par Peter Collingridge.

À ce script j’ai apporté deux modifications majeures :

  • La modification du contenu du tooltip et son redimensionnement ne se font que lorsque l’on entre dans une région (depuis l’extérieur ou depuis une autre)
  • Le rajout d’un positionnement du texte, pour un résultat optimal sur tous les navigateurs

Ma fonction showTooltip() devient donc :

function showTooltip(evt) {
  
	if(curPol != evt.target.getAttribute("id")) {
    	curPol = evt.target.getAttribute("id"); // curPol contient l’id de la dernière région survolée

    	// on récupère le texte à afficher dans le tooltip
    	tooltipText.firstChild.data = evt.target.getAttribute("data-tooltip");
    
    	var rec = tooltipText.getBBox(); // on récupère la boîte englobante du texte

    	// on récupère les dimensions de la boîte
    	var width = Math.round(rec.width);
    	var height = Math.round(rec.height);

    	var r = document.getElementsByTagName('rect'); // on sélectionne tous les rectangles du tooltip

		// les dimensions des rectangles du tootip doivent être plus grandes que le texte pour donner une impression de marge interne
    	var rW = width + 16; 
    	var rH = height + 8;

		// on applique les dimensions à tous les rectangles   
 		for (var i = 0; i < r.length; i++) {
    		r[i].setAttribute("width", rW);
     		r[i].setAttribute("height", rH);
    	}
  
		// on positionne le texte    
		tooltipText.setAttribute('transform','translate(' + (rW/2 - width/2) + ',' + (rH/2 + height/3) + ')');
	}
  
	var CTM = svg.getScreenCTM();
  
  	var x = (evt.clientX - CTM.e + 6) / CTM.a;
  	var y = (evt.clientY - CTM.f + 20) / CTM.d;
  
  	tooltip.setAttribute("transform", "translate(" + x + ", " + y + ")");

  	tooltip.setAttribute("visibility", "visible");
}

Une démo fonctionnelle de cette carte est disponible sur mon site.

Laisser un commentaire