Générateur html de map pour image cliquable

Contenu du snippet

J'eus une grosse frayeur dans le cadre de mon projet V.I.P.E.R.E. concernant les maps de mes planches anatomiques.
En effet, je dus envisager un moment de changer toutes les images de mes ces dernières, ce qui sous entendait de refaire toutes les zones cliquables pour pouvoir naviguer dans mon corps humain.

Trouvant les logiciels de génération de map oh combien fastidieux, laborieux, longs et peu précis, comparés à l'ergonomie des logiciels de retouche d'images, je décidai de créer un générateur de map.

Je voulais :

- Par les calques de mon logiciel d'infographie préféré dessiner les zones cliquables
- Aller chercher cette image
- Modifier éventuellement le ou les liens ainsi que la ou les infobulles dynamiquement
- Faire un copier / coller du HTML de MAP généré dans ma page web

Le résultat se trouve dans le fichier Map.php.

Vous pouvez l'essayer en vous rendant sur http://www.vipere.lekod.com/Francais/Map.php

Pré-requis : Installer la bibliothèque php_gd2

A faire : Renseigner les constantes du script

Alerte : Ce script consomme pas mal de ressource processeur. De plus, plus l'image est grande et fournie, plus long il met à se terminer.
C'est pour cela que j'ai bridé ma version de démo afin de ne pas saturer mon serveur.

Source / Exemple :


<html>
<html dir="LTR">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="Title" lang="fr" content="V.I.P.E.R.E.">
<meta name="Author" lang="fr" content="Florent Benetiere">
<meta name="Reply-to" content="tnerolf@lekod.com">
<meta name="Copyright" content="Florent Benetiere">
<meta name="revisit-after" content="8">
<meta name="Robot" content="index,follow,all">
<meta http-equiv="pragma" content="no-cache">
<TITLE>Générateur de MAP pour image cliquable</TITLE>
</head>
<body>
<?php
/*Auteur : Florent Bénetière tnerolf@lekod.com

L'extraction des contours étant longue, on désactive la limite de temps d'exécution pour ce script*/
set_time_limit(3600);

//Renseignez la constante Chemin_copie_img avec un chemin local où copier le fichier image téléchargé
define("Chemin_copie_img","[Chemin local du stockage de l'image téléchargée]",true);
/*Renseignez la constante Chemin_URL_img avec un chemin http pour indiquer le src de l'image
 S'il n'y en a pas, saisissez la même valeur que Chemin_copie_img*/
define("URL_img","http://[URL vers le répertoire contenant l'image en ligne]",true);
//Renseignez la constante Taille_fichier_max avec la taille maximale en octets que vous accepter pour un fichier.
define("Taille_fichier_max",[Taille en octets],true);
//Renseignez la constante DimX_max avec la largeur maximale de l'image en pixel que vous acceptez
define("DimX_max",[Taille en pixels],true);
//Renseignez la constante DimY_max avec la hauteur maximale de l'image en pixel que vous acceptez
define("DimY_max",[Taille en pixels],true);
//Les variables globales
$Image=0;$Tol_Min;$Tol_Max;$Dim;$x=0;$y=0;$Save_x=0;$Save_y=0;$Compteur=0;$Coord_pixels;

$Pixels;$Zones;$En_trop;
/*
 $Pixels permet de récupérer toutes les coordonnées des contours des formes opaques
 $Zones permet de générer l'HTML des coordonnées des Map

  • /
function Utilise($x,$y) { //Cette fonction regarde dans tous le code HTML des Maps si les coordonnées d'un pixel sont déja présentes global $Zones,$Pixels; if(!$Zones) return; //On regarde d'abord si c'est un contour if(in_array("~".$x.",".$y,$Pixels)) { foreach($Zones as $HTML) { if(preg_match("&~".$x.",".$y."~&",$HTML))return true; } return false; } else return true;//Pour que les pixels qui ne sont pas des contours ne soient pas considérés comme inutilisés. } function Transp($Palette,$x,$y) { global $Tol_Min,$Tol_Max,$Dim; /* Si les coordonnées débordent de l'image, les valeurs de $Palette sont à 0 ce qui correspond à un Noir opaque. Or, si le pixel en 0,0 n'est pas de cette couleur, les pixels de dépassement d'image (-1 et > $Dim["x"] et $Dim["y"]. sont obligatoirement considérés comme opaques au lieu de transparents. On force donc la transparence.
  • /
if($x>=$Dim["x"]||$y>=$Dim["y"]||$x<0||$y<0) { return true; } elseif ( $Palette["red"]>=$Tol_Min["Rouge"] && $Palette["red"]<=$Tol_Max["Rouge"] && $Palette["green"]>=$Tol_Min["Vert"] && $Palette["green"]<=$Tol_Max["Vert"] && $Palette["blue"]>=$Tol_Min["Bleu"] && $Palette["blue"]<=$Tol_Max["Bleu"] ) { return true;//=>Pixel transparent } else return false; } function Est_contour($x,$y) { /* Cette fonction regarde dans les 8 directions par rapport à la portée passée en argument. Si tous les pixels adjacents sont opaques alors on ne prend pas le pixel actif
  • /
global $Image,$Dim,$Pixels,$Coord_pixels,$Tol_Min,$Tol_Max,$En_trop; $Palette=imagecolorsforindex($Image, imagecolorat($Image,$x,$y)); if(!Transp($Palette,$x,$y)) { //On regarde l'opacité des pixels adjacents //N $Abs=$x;$Ordo=$y-1;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='N|'; //NE $Abs=$x+1;$Ordo=$y-1;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='NE|'; //E $Abs=$x+1;$Ordo=$y;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='E|'; //SE $Abs=$x+1;$Ordo=$y+1;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='SE|'; //S $Abs=$x;$Ordo=$y+1;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='S|'; //SO $Abs=$x-1;$Ordo=$y+1;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='SO|'; //O $Abs=$x-1;$Ordo=$y;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='O|'; //NO $Abs=$x-1;$Ordo=$y-1;$Palette=imagecolorsforindex($Image, imagecolorat($Image,$Abs,$Ordo)); if(!Transp($Palette,$Abs,$Ordo)) $Cardinal.='NO'; if($Cardinal!='N|NE|E|SE|S|SO|O|NO') { /*Il s'agit donc d'un contour. On "double" l'épaisseur du trait correspondant au contour des formes car autrement on a un plantage lorsque deux pixels de contour ne sont séparés que par un pixel transparent. En effet, les pixels précédents sont déja pris et il n'est plus possible de déterminer la suite du contour. Exemple: Légende : Chiffres : Parcours du contour Ok, E pour Erreur 12345 XXXX6 7 89 E0 On renseigne $Pixels en insérant dans $Pixels les pixels adjacents au pixel de contour trouvé et $En_trop qui servira plus tard à supprimer les pixels superflus. Le pixel de contour réel n'est pas inséré car il sera forcément entourés de pixels adjacents, donc il sera opaque*/ for($a=0;$a<8;$a++) { switch($a) { case 0: $Testx=$x;$Testy=$y-1;//N break; case 1: $Testx=$x+1;$Testy=$y-1;//NE break; case 2: $Testx=$x+1;$Testy=$y;//E break; case 3: $Testx=$x+1;$Testy=$y+1;//SE break; case 4: $Testx=$x;$Testy=$y+1;//S break; case 5: $Testx=$x-1;$Testy=$y+1;//SO break; case 6: $Testx=$x-1;$Testy=$y;//O break; case 7: $Testx=$x-1;$Testy=$y-1;//NO break; } $Pixels[]='~'.$Testx.','.$Testy; $Taille=count($Pixels)-1; $Coord_pixels[$Taille]["x"]=$Testx;$Coord_pixels[$Taille]["y"]=$Testy; $En_trop[]=array("Cle_Pixels"=>$Taille); } return true; } } } function Next_contour() { global $Zones,$x,$y,$Save_x,$Save_y,$Compteur,$Taille,$Dim; ++$Compteur; static $Prov; if(!$Prov["x"]) { $Prov["x"]=$x;$Prov["y"]=$y; } /*On regarde si un pixel adjacent au pixel en cours correspond au premier pixel du contour N = $y-1 NE = $x+1 et $y-1 E = $x+1 SE = $x+1 et $y+1 S = $y+1 SO = $x-1 et $y+1 O = $x-1 NO = $x-1 et $y-1 $Compteur permet de ne pas finaliser la MAP tant que l'on n'est pas positionné sur le quatrième pixel. Exemple : 1|2 x|3 x|4 Premier pixel détecté : 1 => $Compteur=1 Second pixel détecté : 2 => $Compteur=2 mais le pixel à l'Ouest est celui du démarrage du contour donc, si on ne bride pas, le contour sera finalisé. Troisième pixel détecté : 3 => $Compteur=3 mais le pixel au Nord-Ouest est celui du démarrage du contour donc, si on ne bride pas, le contour sera finalisé. Au delà du troisième pixel, si les coordonnées d'un pixel adjacent correspondent à celle du premier pixel de contour cela signifie que l'on a fait le tour du contour. On détermine quelle est la direction en cours et en fonction de celle-ci, on détermine à partir de quel cardinalité on commence et quel sens on prend (aiguille d'une montre ou l'inverse) pour tourner autours du pixel $x==$Prov["x"] && $y==$Prov["y"] => Initialisation $x==$Prov["x"] && $y <$Prov["y"] => N $x >$Prov["x"] && $y <$Prov["y"] => NE $x >$Prov["x"] && $y==$Prov["y"] => E $x >$Prov["x"] && $y >$Prov["y"] => SE $x==$Prov["x"] && $y >$Prov["y"] => S $x <$Prov["x"] && $y >$Prov["y"] => SO $x <$Prov["x"] && $y==$Prov["y"] => O $x <$Prov["x"] && $y <$Prov["y"] => NO "0|-1" => N "1|-1" => NE "1|0" => E "1|1" => SE "0|1" => S "-1|1" => SO "-1|0" => O "-1|-1" => NO*/ if(($x==$Prov["x"] && $y==$Prov["y"]) ||($x==$Prov["x"] && $y <=$Prov["y"]) ||($x >=$Prov["x"] && $y <=$Prov["y"]) ||($x >=$Prov["x"] && $y==$Prov["y"]) ||($x >=$Prov["x"] && $y >=$Prov["y"])) { $Next=array("0|-1","1|-1","1|0","1|1","0|1","-1|1","-1|0","-1|-1" ); } elseif(($x==$Prov["x"] && $y >$Prov["y"]) ||($x <$Prov["x"] && $y >$Prov["y"]) ||($x <$Prov["x"] && $y==$Prov["y"]) ||($x <$Prov["x"] && $y <$Prov["y"])) { $Next=array("0|1","-1|1","-1|0","-1|-1","0|-1","1|-1","1|0","1|1"); } /* Et pourquoi tout cela me direz-vous ? C'est très simple : Lorsqu'un prochain pixel est une diagonale, cela laisse les pixels "perpendiculaires" en statut inutilisé. Or, pour les diagonales allant vers l'Ouest, en partant de Nord, un mauvais pixel sera inclu dans le contour de la MAP et ensuite il n'y aura plus de prochain pixel pour poursuivre la génération de ce contour, ce qui plantera le script. Exemple avec Sud-Ouest : Légende : [X] => Pixels de contour trouvé [Y] => Pixel considéré comme faisant partie du contour [Z] => Prochain pixel à intégrer [P] => Pixel considéré comme plein (ne faisant pas partie du contour [o] => Pixel transparent [X][X][X][o][o][o] [P][P][X][X][X][o] [P][P][P][Y][X][o] [P][P][P][X][o][o] [P][P][Z][o][o][o] En arrivant au [X] le plus bas, si on suit le sens des aiguilles d'une montre, le pixel [Y] sera intégré dans les coordonnées de la MAP car il sera considéré comme inutilisé. Ensuite, lorsque l'on fera le tour de ce pixel pour trouver le pixel suivant, on n'en trouvera pas car tous les pixels adjacents à celui-ci seront utilisés.
  • /
foreach($Next as $Val) { $Test=explode("|", $Val); if(!Utilise(($x+$Test[0]),($y+$Test[1]))) { $Prov["x"]=$x;$Prov["y"]=$y;//On garde le pixel trouvé pour voir la provenance lors du traitement du pixel suivant. //Pour les diagonales, on ajoute dans les pixels utilisés celui qui n'a pas été pris par la diagonale, afin qu'il ne puisse faire dévier le tracé du contour ultérieurement. switch($Test[0].'|'.$Test[1]) { case "1|-1": //NE $Zones[$Taille].='~'.($x+1).','.$y; break; case "1|1": //SE $Zones[$Taille].='~'.$x.','.($y+1); break; case "-1|1": //SO $Zones[$Taille].='~'.($x-1).','.$y; break; case "-1|-1": //NO $Zones[$Taille].='~'.$x.','.($y-1); break; } $x+=$Test[0];$y+=$Test[1]; $Zones[$Taille].='~'.$x.','.$y; return 1; } } if((($x==$Save_x && $y-1==$Save_y) ||//N ($x+1==$Save_x && $y-1==$Save_y) ||//NE ($x+1==$Save_x && $y==$Save_y) || //E ($x+1==$Save_x && $y+1==$Save_y) ||//SE ($x==$Save_x && $y+1==$Save_y) || //S ($x-1==$Save_x && $y+1==$Save_y) ||//SO ($x-1==$Save_x && $y==$Save_y) ||//O ($x-1==$Save_x) && $y-1==$Save_y)&& $Compteur>3)//NO { $Zones[$Taille]='<AREA SHAPE="poly" COORDS="'.$Zones[$Taille].'~'.$x.','.$y.'" HREF="'.$_POST["Lien"].'" title="'.$_POST["Infobulle"].'">';//On ferme la balise Map $Save_x=NULL;$Save_y=NULL;$Compteur=0; unset($Prov); return 2; } //Aucun pixel de prochain contour => Le contours est ouvert => on le ferme pour ne pas planter le script $Zones[$Taille]='<AREA SHAPE="poly" COORDS="'.$Zones[$Taille].'" HREF="'.$_POST["Lien"].'" title="'.$_POST["Infobulle"].'">';//On ferme la balise Map $Save_x=NULL;$Save_y=NULL;$Compteur=0; unset($Prov); return 0; } function Trouve_bornes($Map) { $Bornes=array("Min_x"=>0,"Max_x"=>0,"Min_y"=>0,"Max_y"=>0); preg_match_all("&~(:digit:+),(:digit:+)~&",$Map,$Result); /*$Result[1]=Abscisses, $Result[2]=Ordonnées On détermine les bornes minimales et maximales des abscisses et des ordonnées*/ array_multisort($Result[1],SORT_ASC,SORT_NUMERIC); array_multisort($Result[2],SORT_ASC,SORT_NUMERIC); $Bornes["Min_x"]=$Result[1][0];$Bornes["Max_x"]=$Result[1][count($Result[1])-1]; $Bornes["Min_y"]=$Result[2][0];$Bornes["Max_y"]=$Result[2][count($Result[2])-1]; return $Bornes; } function Suppr_superflus($Map) { global $Zones; /* Lorsque l'on a épaissi les contours, on a créé deux zones de map, l'une extérieure au contour et l'autre intérieure. Exemple : 111111111 Légende : 1XXXXXXX1 X : Contour original supprimé car considéré comme opaque par l'épaississement. 1X22222X1 1 : Contour extérieur. 1X2 2X1 2 : Contour intérieur. 1X2 2X1 1X22222X1 1XXXXXXX1 111111111 Automatiquement, la zone extérieure est prise en premier pour générer le contour car ses pixels sont détectés avant ceux de la zone intérieure. On suprimme donc la zone intérieure. - On classe les coordonnées par l'abscisse et l'ordonnée - On récupère l'abscisse et l'ordonnée minimale et maximale de la zone - Pour chaque zone antérieurement générée on regarde si l'absisse et l'ordonnée minimales sont à l'intérieure de la zone - Si c'est le cas => Zone interne => on la supprimme. - Pour chaque zone précédemment générée : - On récupère les bornes - On regarde si la surface délimitée par les bornes de $Map sont comprises dans la zone délimitée par les bornes de la zone - Si oui : - On supprime la zone en cours de génération. - On supprime de $Pixels tous les pixels qui ont servi à générer la zone
  • /
$Bornes_Map=Trouve_bornes($Map); foreach($Zones as $Val) { if($Map!=$Val) { $Bornes_zone=Trouve_bornes($Val); if($Bornes_Map["Min_x"]>=$Bornes_zone["Min_x"] && $Bornes_Map["Max_x"]<=$Bornes_zone["Max_x"] && $Bornes_Map["Min_y"]>=$Bornes_zone["Min_y"] && $Bornes_Map["Max_y"]<=$Bornes_zone["Max_y"]) { $Zones[array_search($Map,$Zones)].="A ne pas prendre"; return; } } } } if(!$_FILES['Fichier']['tmp_name']) { echo ' <script language="javascript" type="text/javascript"> function Valid() { with(document.Form1) { if(Fichier.value.length==0) { alert("Sans fichier à charger je n\'ai que mes yeux pour pleurer"); Fichier.focus(); } else if(Tolerance.value<0||Tolerance.value>100 || isNaN(Tolerance.value)) { alert("La tolérance doit être un nombre compris entre 0 et 100"); Tolerance.focus(); } else if(Map.value.length==0) { alert("Sans nom de Map, pas de prise de cap !"); Map.focus(); } else if(Lien.value.length==0) { alert("Sans lien je ne peux rien."); Lien.focus(); } else { submit(); } } } </script> <form Enctype="multipart/form-data" Name="Form1" Method="post" action="'.htmlentities($_SERVER['PHP_SELF']).'"> <input type="hidden" name="MAX_FILE_SIZE" value="'.Taille_fichier_max.'"> <h1>Générateur de Map pour images cliquables</h1> <p>Image à mapper sachant que le premier pixel en haut à gauche sera celui définissant <b>&quot;la transparence&quot;</b>.<br>La taille du fichier ne doit pas dépasser <b>'.number_format(Taille_fichier_max/1024000,2,',',' ').' Mo</b>. <br>Ses dimensions maximales sont de <b>'.DimX_max.'</b> pixels de large et de <b>'.DimY_max.'</b> pixels de haut.<br>Les formats acceptés sont <b>GIF et PNG</b></p> <p>Image à traiter : <input type="file" name="Fichier"></p> <p>Le premier pixel en haut à gauche servira à définir la &quot;transparence&quot;. Indiquez la tolérance <input type="text" name="Tolerance" value="0" maxlength="3" size="3" style="text-align:right;"> %</p> <p>Indiquez le nom de la MAP <input type="text" name="Map" maxlength="100" size="50" value="MAP_Lekod"></p> <p>&nbsp;Indiquez le lien par défaut <input type="text" name="Lien" maxlength="100" size="50" value="http://Mon_site.com"></p> <p>Indiquez l\'infobulle par défaut <input type="text" name="Infobulle" maxlength="100" size="50" value="Mon infobulle"></p> <p><input type="button" name="B_Valid" value="Générer la Map" onclick="Valid()"></p> <H2 align="center">Ce processus étant <u>assez long</u>,<br> il vous faudra faire montre de <u>patience</u>.</H2> </div> '; } else { //On vérifie que les dimensions et la taille sont dans les limites if($_FILES['Fichier']['size']>Taille_fichier_max) { unlink($_FILES['Fichier']['tmp_name']); die('La taile du fichier excède les <b>'.number_format(Taille_fichier_max/1024000,2,',',' ').'</b> Mo<br> Abandon de la génération'); } switch(exif_imagetype($_FILES['Fichier']['tmp_name'])) { case IMAGETYPE_GIF: $Image=imagecreatefromgif($_FILES['Fichier']['tmp_name']);$Ext='.gif'; break; case IMAGETYPE_PNG: $Image=imagecreatefrompng($_FILES['Fichier']['tmp_name']);$Ext='.png'; break; default: echo '<script language="javascript">alert("Le format du fichier selectionne n\'est pas reconnu !"); window.location=\''.$_SERVER['PHP_SELF'].'\'; </script>'; unlink($_FILES['Fichier']['tmp_name']);die(); break; } $Dim=array("x"=>imagesx($Image),"y"=>imagesy($Image)); if($Dim["x"]>DimX_max||$Dim["y"]>DimY_max) { imagedestroy($Image); die('Les dimensions de l\'image sont supérieures à <b>'.DimX_max.'</b> pixels de large et à <b>'.DimY_max.'</b> pixels de haut.'); } // La couleur de transparence est le pixel en (0,0) $Transparence=imagecolorsforindex($Image, imagecolorat($Image,0,0)); //On détermine les couleurs minimales et maximales de tolérance $Tol_Min["Rouge"]=intval($Transparence["red"]-($Transparence["red"]*$_POST["Tolerance"]/100)); $Tol_Max["Rouge"]=intval($Transparence["red"]+($Transparence["red"]*$_POST["Tolerance"]/100)); $Tol_Min["Vert"]=intval($Transparence["green"]-($Transparence["green"]*$_POST["Tolerance"]/100)); $Tol_Max["Vert"]=intval($Transparence["green"]+($Transparence["green"]*$_POST["Tolerance"]/100)); $Tol_Min["Bleu"]=intval($Transparence["blue"]-($Transparence["blue"]*$_POST["Tolerance"]/100)); $Tol_Max["Bleu"]=intval($Transparence["blue"]+($Transparence["blue"]*$_POST["Tolerance"]/100)); /*On parcourt le tableau - Si le pixel est compris dans la plage de tolérance, on n'insère pas ses coordonnées dans $Zones
  • /
for($a=0;$a<=$Dim["y"];$a++) { for($b=0;$b<=$Dim["x"];$b++) { Est_contour($b,$a); } } imagedestroy($Image); if($Pixels[0]=='')die('Il n\'y a rien à mapper.<br>Réduisez la tolérance ou bien changez les zones transparentes'); /*En épaississant les contours précédemment, on a virtualisé des pixels "opaques" On les supprime de $Pixels*/ foreach($Pixels as $Cle => $Val) { $Poid=0; $x=$Coord_pixels[$Cle]["x"];$y=$Coord_pixels[$Cle]["y"]; if(in_array('~'.$x.','.($y-1),$Pixels)) ++$Poid;//N if(in_array('~'.($x+1).','.($y-1),$Pixels)) ++$Poid;//NE if(in_array('~'.($x+1).','.$y,$Pixels)) ++$Poid;//E if(in_array('~'.($x+1).','.($y+1),$Pixels)) ++$Poid;//SE if(in_array('~'.$x.','.($y+1),$Pixels)) ++$Poid;//S if(in_array('~'.($x-1).','.($y+1),$Pixels)) ++$Poid;//SO if(in_array('~'.($x-1).','.$y,$Pixels)) ++$Poid;//O if(in_array('~'.($x-1).','.($y-1),$Pixels)) ++$Poid;//NO if($Poid==8) $En_trop[$Cle]["Opaque"]=true; } //Maintenant qu'on a marqué tous les pixels "opaques", on les enlève de $Pixels foreach($En_trop as $Cle=>$Val) { if($Val["Opaque"]) { unset($Pixels[$Val["Cle_Pixels"]]); unset($Coord_pixels[$Val["Cle_Pixels"]]); unset($En_trop[$Cle]); } } /* Maintenant qu'on a les contours, pour chaque point, on détermine le suivant à la manière du Petit Poucet, ce qui permet de générer les Maps
  • /
foreach($Pixels as $Cle=>$Valeur) { //On extrait les coordonnées du code HTML $x=$Coord_pixels[$Cle]["x"];$y=$Coord_pixels[$Cle]["y"]; if(!Utilise($x,$y)) { $Save_x=$x;$Save_y=$y; //On instancie une nouvelle zone $Zones[].='~'.$x.','.$y; $Taille=count($Zones)-1; while(!preg_match('~^<AREA SHAPE="poly"~',$Zones[$Taille])) { while(1==1) { $Result=Next_contour(); if($Result==0 || $Result==2) {/*$Result==0)=>Aucun pixel de prochain contour => On traite le pixel suivant en finalisant la Map $Result==2)=>On a finit de faire le tour de la forme => Finalisation du HTML de la Map*/ Suppr_superflus($Zones[$Taille]);//On nettoie des zones intérieures ou batardes break 2; } } } } } $Taille=count($Zones); for($a=0;$a<$Taille;$a++) { if(!strpos($Zones[$a],"A ne pas prendre")) { /*Malgré toute ma bonne volonté pour ne pas mettre de zones superflues et de supprimmer tous les pixels inutiles à l'élaboration des maps, il arrive qu'il soit possible de se retrouver avec des zones d'un pixel. On ne les prend pas en compte.
  • /
$Nbre_coord=explode(",",$Zones[$a]); if(count($Nbre_coord)==2)//Cela veut dire qu'il n'y a qu'un pixels de contour { unset($Zones[$a]); } else { $Map.=str_replace(array("\"~","~",-1),array("\"",",",0),$Zones[$a]); } }//-1 est présent lorsqu'en épaississant les contours on déborde vers les bords haut et/ou gauche de l'image. else//Par soucis d'esthétisme, on remet à la place un 0. On pourrait faire pareil pour les bords supérieurs lorsque les contours touchent à droite et/ou en bas { unset($Zones[$a]); } } //On déplace le fichier téléchargé pour affichage de l'image $Fichier=Chemin_copie_img.'Map_'.time().$Ext; copy($_FILES['Fichier']['tmp_name'],$Fichier); echo ' <script language="javascript" type="text/javascript"> function Changt() { var Areas=document.getElementsByTagName("AREA"); var Textes=document.getElementsByTagName("input"); var Map=document.getElementsByTagName("MAP"); var Compteur=0 Map=Map[0]; Map.innerHTML=Map.innerHTML.replace(/title/gi,"alt"); for(a=0;a<Textes.length;a++) { if(Textes[a].name.substring(0,4)=="Lien") { Areas[Compteur].href=Textes[a].value; } else if(Textes[a].name.substring(0,9)=="Infobulle") { Areas[Compteur].alt=Textes[a].value; Compteur++; } } //Firefox ne reconnait pas les alt. On change cette propriété en title Map.innerHTML=Map.innerHTML.replace(/alt/gi,"title"); document.Form1.Result.value="<MAP NAME=\"'.$_POST["Map"].'\">"+Map.innerHTML+"</MAP>"; } </script> <MAP NAME="'.$_POST["Map"].'">'. $Map.'</MAP> <P name="P_Image" align="center"> <img src="'.str_replace(Chemin_copie_img,URL_img,$Fichier).'" name="Image" usemap="#'.$_POST["Map"].'"> </p> <p><textarea name="Result" rows="10" cols="100" wrap="soft"><MAP NAME="'.$_POST["Map"].'">'. $Map.'</MAP></textarea></p> <p>Pour changer le lien d\'une zone de l\'image modifiez la valeur dans la zone <b>"Changer le lien"</b>. <p>Pour changer l\'infobulle d\'une zone de l\'image modifiez la valeur dans la zone <b>"Changer l\'infobulle"</b></p> <table width="100%"> <tr> <td> <p align="center">Changer le lien</p> </td> <td > <p align="center">Changer l\'infobulle</p> </td> </tr>'; //On met de quoi changer la valeur des liens et des infobulles foreach($Zones as $Cle=>$Val) { echo '<tr> <td align="center"> <input type="text" name="Lien'.$Cle.'" value="'.$_POST["Lien"].'" size="50%"> </td> <td align="center"> <input type="text" name="Infobulle'.$Cle.'" value="'.$_POST["Infobulle"].'" size="50%"> </td> </tr>'; } echo '</table> <p align="center"> <input type="button" name="B_Valid" value="Valider les changements" onclick="Changt()"> &nbsp;&nbsp;<input type="button" name="B_Reinit" value="Play it again Sam" onclick="javascript:window.location=\''.htmlentities($_SERVER['PHP_SELF']).'\'"></p> '; } ?> </form> </body> </html>

Conclusion :


Une petite astuce :

Pour avoir une MAP évidée, séparez la forme d'une bande de minimum trois pixels d'épaisseur.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.