Google Maps API : gestionnaire automatique de marqueurs

Ingénierie web | JavaScript | Web 2.0

Comme nous l'avons vu dans le billet précédent sur le gestionnaire de marqueurs, l'API Google Maps ne gère pas automatiquement le remplacement d'un groupe de marqueurs proches par un marqueur unique à faible facteur de zoom. Heureusement, Jef Poskanzer a écrit une librairie implémentant cette fonctionnalité : Clusterer.

Partons de l'exemple 9 qui est identique à l'exemple 4 d'un précédent billet auquel j'ai ajouter une concentration importante de marqueurs à l'est de Paris. Déclarons la librairie dans l'en-tête HTML :

<script src="http://www.acme.com/javascript/Clusterer2.jsm" type="text/javascript"></script>

La gestion automatique se fait en déclarant une variable clusterer, instanciée dans la fonction load :

var clusterer; function load() { if (GBrowserIsCompatible()) { map = new GMap2(document.getElementById("map")); map.addControl(new GLargeMapControl()); map.addControl(new GMapTypeControl()); map.setCenter(new GLatLng(46.85, 1.75), 6); clusterer = new Clusterer(map); clusterer.SetMaxVisibleMarkers(10); clusterer.SetMinMarkersPerCluster(5); GDownloadUrl("exemple10.json", setup_json); } else { alert("Desole, l'API Google Maps n'est pas compatible avec votre navigateur."); } }

Un objet Clusterer possède 4 méthodes :

  • SetMaxVisibleMarkers(n) : définie le nombre de marqueurs au delà duquel le clustering est mis en place (150 par défaut).
  • SetMinMarkersPerCluster(n) : définie le nombre minimum de marqueurs constituant un cluster (5 par défaut).
  • SetMaxLinesPerInfoBox(n) : définie le nombre de ligne s'affichant dans la fenêtre d'information du marqueur correspondant au cluster (10 par défaut).
  • SetIcon(icon) : définie l'icône du marqueur correspondant au cluster si celui par défaut ne convient pas.

Il suffit ensuite de remplacer chaque appel à map.addOverlay(marker) par un appel à clusterer.AddMarker(marker, title) (où title est la ligne du marqueur réel qui s'affichera dans la fenêtre d'information du marqueur correspondant au cluster) et chaque appel à map.removeOverlay(marker) par un appel à clusterer.RemoveMarker(marker). Exemple dans la fonction setup_json :

setup_json = function(json, status) { var data = eval('(' + json + ')'); for (var i=0; i<data.markers.length; i++) { var point = new GLatLng(data.markers[i].lat, data.markers[i].lng); var marker = createMarker(point, data.markers[i].html); clusterer.AddMarker(marker, data.markers[i].html); } }

Le résultat est visible sur l'exemple 10.

Cette solution permet de rendre de bons services, mais n'est toute fois pas idéale. En effet, le clustering est lié au nombre de marqueurs plutôt qu'à leur densité. Ainsi, deux marqueurs supperposés ne seront vus que comme un seul marqueur à fort grossissement (en l'absence de clustering). D'autre part, l'algorithme n'est pas très précis : sur l'exemple 10, le marqueur placé sur Le Havre a été intégré au cluster bien qu'il en soit assez éloigné !

Les autres billets de cette série sur l'API Google Maps :

Google Maps API : gestionnaire de marqueurs

Ingénierie web | JavaScript | Web 2.0

Reprenons notre exploration de l'API Google Maps pour résoudre le problème suivant : comment afficher un unique marqueur regroupant plusieurs marqueurs lorsque le niveau de zoom est faible ? En effet, lorsque le nombre de marqueurs est très important sur une petite région, la carte est difficile à lire et lente à s'afficher. La réponse semble être le gestionnaire de marqueurs GMarkerManager.

Partons de l'exemple 4 d'un précédent billet dans lequel nous déléguons l'affichage des marqueurs à un gestionnaire de marqueurs. Pour cela, on déclare une variable mgr, que l'on instancie dans la fonction load :

var mgr; function load() { if (GBrowserIsCompatible()) { map = new GMap2(document.getElementById("map")); map.addControl(new GLargeMapControl()); map.addControl(new GMapTypeControl()); map.setCenter(new GLatLng(46.85, 1.75), 6); mgr = new MarkerManager(map); GDownloadUrl("exemple04.json", setup_json); } else { alert("Desole, l'API Google Maps n'est pas compatible avec votre navigateur."); } }

L'ajout des marqueurs se fait dans la fonctions setup_json en créant d'abord un tableau de marqueurs, markers, ajouter en une fois à la carte via la fonction addMarkers prenant comme second paramètre le niveau de zoom minimum en deçà duquel les marqueurs ne sont pas affichés, et un troisième argument optionnel, le niveau de zoom maximum au delà duquel les marqueurs ne sont pas affichés :

setup_json = function(json, status) { var data = eval('(' + json + ')'); var markers = new Array(); for (var i=0; i<data.markers.length; i++) { var point = new GLatLng(data.markers[i].lat, data.markers[i].lng); var marker = createMarker(point, data.markers[i].html); markers.push(marker); } mgr.addMarkers(markers, 5); mgr.refresh(); }

Le résultat est visible sur l'exemple 8.

On peut appeler plusieurs fois la méthode addMarkers avec différents tableaux de marqueurs pour différents niveau de zoom et gérer ainsi, à la mano, les regroupements de marqueurs. Cela implique donc de calculer, sur le serveur, l'emplacement des marqueurs qui prendront la place d'un ensemble de marqueurs et du niveau de zoom auquel on affiche chacun... Pas simple ! Heureusement il existe une solution toute faite via une librairie JavaScript... Suite au prochain épisode !

Les autres billets de cette série sur l'API Google Maps :

Développer en local une application mashup (Google Maps API, facebook, etc)

Ingénierie web | Web 2.0

Le développement d'une application s'appuyant sur un service externe (mashup) tel que Google Maps ou facebook nécessite de le faire sur un serveur accessible depuis Internet. Cela est imposé par le fournisseur du service qui soit délivre une clé liée au nom du serveur (Google Maps par exemple), soit fait des requêtes directement sur le serveur (facebook). Voici une adaptation d'un tutoriel permettant de développer une telle application sur votre propre poste de développement local (si vous maîtrisez votre réseau).

Il n'y a pas de solution miracle. La seule possibilité est de mettre son poste de développement (le PC) sur Internet. Cela implique de pouvoir faire de la translation de port sur votre routeur NAT. Cette opération varie d'un routeur à un autre. Mais vous aurez généralement besoin de connaître l'adresse IP du PC sur le réseau interne ainsi que son adresse MAC. Pour cela il suffit de taper la commande ifconfig eth0 qui vous sort un truc comme ça (les adresses ci-dessous sont fictives) :

eth0 Lien encap:Ethernet HWaddr 00:12:62:4A:BA:28 inet adr:192.168.0.13 Bcast:192.168.0.255 Masque:255.255.255.0 adr inet6: fa70::153:73ef:fb9a:da16/64 Scope:Lien UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 Packets reçus:55899 erreurs:0 :0 overruns:0 frame:0 TX packets:49661 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 lg file transmission:1000 Octets reçus:62053810 (59.1 MiB) Octets transmis:8498200 (8.1 MiB) Interruption:16

L'adresse IP du PC sur le réseau interne est donc 192.168.0.13 et son adresse MAC 00:12:62:4A:BA:28.

Il suffit de configurer son routeur pour lui indiquer que l'adresse MAC 00:12:62:4A:BA:28 doit toujours être associée à l'adresse IP 192.168.0.13 et que les requêtes reçu par le routeur sur le port 80 doivent être renvoyées vers le port 80 de la machine d'adresse IP 192.168.0.13.

Vous pouvez chercher la procédure adaptée à votre routeur sur le site Port Forward. Dans le cas d'une freebox, il suffit d'aller sur la page de configuration accessible après login, et de remplir le formulaire :


Exemple de configuration sur la Freebox
Exemple de configuration sur la Freebox (agrandir)

Vérifiez que cela fonctionne en pointant votre navigateur vers l'adresse IP publique de votre routeur, récupérable via son interface de configuration ou via le service web What is my IP (88.171.154.137 par exemple). Vous devez voir la racine de votre serveur web... Vous pouvez même donner un nom DNS à cette adresse IP. Il ne vous reste plus qu'à générer la clé du service pour cette adresse IP !

Google Maps API : coordonnées d'un marqueur

Ingénierie web | JavaScript | Web 2.0

Ce sixième et dernier billet (pour le moment du moins) sur l'API Google Maps vous apprendra à récupérer les coordonnées d'un marqueur déplaçable.

Partons de l'exemple 6 du billet précédent. Les coordonnées sont des propriétés du marqueur qu'il suffit de récupérer à la fin d'un glisser/déposer dans la fonction createMarker :

GEvent.addListener(marker, "dragend", function() { htm = html + '<br />Lat_1 = ' + point.lat() + ' Lat_2 = ' + marker.getPoint().lat(); htm = htm + '<br />Lng_1 = ' + point.lng() + ' Lng_2 = ' + marker.getPoint().lng(); marker.openInfoWindowHtml(htm); });

Voilà ! Nous avons tout ce dont nous avons besoin pour faire un formulaire d'enregistrement de coordonnées en plus de l'affichage de marqueurs correspondants à des emplacements fournis sous forme de données JSON.

Le résultat est visible sur l'exemple 7.

Les autres billets de cette série sur l'API Google Maps :

Flux XML