4: Google Maps : Marqueurs et fenêtres d'informations

16 avril 2008Javascript, cartographie, googlemaps
 Cet article a été rédigé il y a plusieurs années et peut ne plus être tout à fait à jour…

Les trois premiers articles de cette série consacrée à google-maps nous ont permis de :

Nous allons à présent voir comment :

  • Afficher un ou plusieurs marqueur(s), éventuellement personnalisé(s) sur notre carte,
  • et ouvrir une fenêtre d'information lors du clic sur l'un d'entre eux.

Note : Au moment où j'écris cet article, je considère que vous avez lu et compris les trois précédents.
Si ce n'est pas le cas, n'hésitez pas à les consulter !

Note : Vous trouverez en pièce jointe à cet article une archive regroupant l'ensemble des exemples utilisés tout au long de cet article.


Squelette utilisé pour les exemples de cet article

Comme toujours - ou presque - cet article commence par le code de la page qui nous servira de base pour quasiment tous nos exemples.
Cette page se compose, à son habitude :

  • de quelques lignes de XHTML,
  • d'un soupçon de code PHP pour dynamiser le tout, et faciliter le développement,
  • et de JavaScript permettant l'affichage de la carte.


Page XHTML cliente

Pour commencer, voici le code de la page (X)HTML au sein de laquelle sera affichée la page :

<?php require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'googlemaps-key.php');?>
<?php header('Content-type: text/html; charset=UTF-8'); ?>
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Découverte de l'API Google Maps - Marqueurs et fenêtres d'information</title>

    <script type="text/javascript"
        src="http://www.google.com/jsapi?key=<?php echo $apiKey; ?>">
    </script>

    <script type="text/javascript"
        src="exemple-0.js">
    </script>
</head>
<body>
    <div id="map" style="border: 1px solid black;
            width: 500px; height: 500px;
            margin-left: 30px; margin-top: 30px;
            float: left">
    </div>

    <script type="text/javascript">
        init();
    </script>
</body>
</html>

Encore une fois, rien de bien nouveau sous le soleil :

  • Chargement des fichiers Google Maps depuis le serveur de Google,
  • Chargement du fichier JS où nous placerons notre code,
  • Création d'un élément d'id "map" qui contiendra la carte,
  • Et appel de la fonction d'initialisation que nous déclarerons dans notre fichier JS.

Le tout dans un fichier PHP, pour faciliter le déploiement sur un serveur ou un autre - utilisant des clefs d'API différentes.


Côté PHP serveur

Un second fichier PHP, qui contiendra la définition de la clef d'API :

$apiKey = 'ABQIAAAAnA2FiFc_BknJBrLWqdaYgxT2yXp_ZAY8_ufC3CFXhHIE1NvwkxQe3jGsoyKKo5ZAasrlZefgTF6muQ';

En toute logique, cette définition sera rendue conditionnelle par l'environnement (test, intégration, recette, production, ...) où est lancée la page.


Et code JavaScript affichant la carte

Et pour finir, les deux méthodes JavaScript déclenchant l'affichage de la carte :

La première, chargeant les méthodes de l'API Google Maps, et provoquant l'appel de la seconde lorsque ladite API sera chargée :

var init = function ()
{
    google.load("maps", "2");
    google.setOnLoadCallback(initMap);
}; // init

Et la seconde, responsable de la création de la carte, du lancement d'une recherche de localisation, et de l'affichage de la carte, centrée sur celle-ci :

var initMap = function ()
{
    var map = new google.maps.Map2(document.getElementById('map'));
    map.addControl(new GSmallMapControl());  // Contrôle de zoom, déplacement sur la carte

    var adresse = 'place bellecour, Lyon, france';
    var geocoder = new google.maps.ClientGeocoder();
    geocoder.getLatLng(adresse, function (coord) {
        map.setCenter(coord, 13);  // Centrage sur le point dont on a obtenu les coordonnées depuis l'adresse
        map.setMapType(G_HYBRID_MAP);  // Vue satellite + informations cartographiques

        // TODO : marqueurs, infoWindows, ...

    });

}; // initMap

Vous noterez que je continue à travailler avec mon exemple habituel, la Place Bellecour, à Lyon.


Rendu

Et voila la capture d'écran obtenue lorsque l'on affichage la page "squelette" :

carte-vide.png

On retrouve, en toute logique, le résultat obtenu au cours des articles précédents.


Ajouter des marqueurs sur une carte Google Maps

Lorsque vous souhaitez afficher une carte sur votre site, votre but premier est probablement de permettre à vos utilisateurs

  • soit de se repérer,
  • soit de repérer un lieu

La carte en elle-même n'est donc généralement pas porteuse de toute l'information que vous auriez tendance à vouloir qu'elle présente.

Pour répondre à cette problématique, l'API Google Maps permet d'ajouter des "marqueurs" (en anglais, un "marker", des "markers") sur une carte.
Ceux-ci permettent d'indiquer une position précise sur la carte.


Ajouter un marqueur "standard"

Pour ajouter un marqueur à une carte, le principe est le suivant :

  • Un marqueur est une instance d'objet GMarker
  • Une instance d'objet GMarker se crée sur une instance d'objet GPoint
  • Et une instance d'objet GPoint se crée sur une latitude et une longitude.
  • Une fois l'instance d'objet GMarker obtenue, le marqueur s'ajoute à la carte à l'aide de la méthode addOverlay.

Exemple de base : Ajout d'un marqueur à la carte

Autre dit, si vous connaissez les latitude et longitude d'un point, l'ajout d'un marqueur à cette position se fera de la manière suivante :

var point = new GPoint(45.779915302498935, 4.803814888000488);  // Création du point correspondant aux coordonnées nous intéressant
var marker = new GMarker(point);  // Création d'un marqueur localisé sur ce point
map.addOverlay(marker);  // Et ajout du marqueur à la carte

En injectant cette portion de code au sein du squelette présenté plus haut, nous obtiendrons l'affichage suivant :

carte-ex1-marqueur.png

(Comme de bien entendu, les coordonnées utilisées pour cet exemple sont... Celles correspondant au centre de la carte - ce qui n'est pas une obligation, comme nous le verrons par la suite.)


Un peu plus loin : Ajout de plusieurs marqueurs

Pour aller un peu plus loin, voyons comment positionner plusieurs marqueurs sur la même carte.

Dans le principe, nous allons :

  • déclarer une liste contenant les coordonnées de toutes les stations de métro de Lyon,
  • et parcourir cette liste, en ajoutant un marqueur à l'emplacement de chaque station.

Voila pour la liste :

// Liste des stations de metro de Lyon
var stationsMetro = [
    // Ligne A
    {ligne: 'A', loc: 'L. Bonnevay Astroballe', lat: 45.76434960130271, lng: 4.91063117980957},
    {ligne: 'A', loc: 'Cusset', lat: 45.76482861073421, lng: 4.901275634765625},
    // ...

    // Ligne B
    {ligne: 'B', loc: 'Charpennes - Charles Hernu', lat: 45.77021718342828, lng: 4.86393928527832},
    {ligne: 'B', loc: 'Brotteaux', lat: 45.76692422863731, lng: 4.860076904296875},
    // ...

    // Ligne C
    {ligne: 'C', loc: 'Cuire', lat: 45.7850630013786, lng: 4.8332977294921875},
    {ligne: 'C', loc: 'Henon', lat: 45.77907726002176, lng: 4.827632904052734},

    // ...

    // Ligne D
    {ligne: 'D', loc: 'Gare de Vaise', lat: 45.77955614297965, lng: 4.804630279541016},
    {ligne: 'D', loc: 'Valmy', lat: 45.77464739768229, lng: 4.806003570556641}
    // ...

]; // stationsMetro

(Je vous laisse compléter à loisir ^^ )

Et pour le code la parcourant :

// Ajout d'un marqueur pour chacune des stations de metro de Lyon
for (var i=0 ; i<stationsMetro.length ; i++)
{
    map.addOverlay(createMarker(stationsMetro[i]));
}

Par soucis de lisibilité, le code de création de chaque marqueur a été exporté au sein de la fonction createMarker :

var createMarker = function(infosStation)
{
    var point = new GPoint(infosStation.lng, infosStation.lat);
    var marker = new GMarker(point);
    return marker;
}; // createMarker

Cette fonction ne faisant, dans ce cas relativement basique, que créer le marqueur, et le retourner.

Une fois ces portions de code exécutées, nous obtenons une carte... portant plusieurs marqueurs :

carte-ex2-plusieurs-marqueurs.png

Nous retrouvons le tracé des quatre lignes de métro lyonnaises !

(Au besoin, vous trouverez la liste complète des stations dans les exemples en pièce jointe à cet article)


Marqueurs personnalisés

La carte regroupant les dizaines de marqueurs des différentes stations de toutes les lignes de métro fait - il faut l'avouer - quelque peu fouilli : il est difficile de dissocier les lignes les unes des autres...
...Et je vous laisse imaginer ce qu'il en serait pour d'autres villes - quid de Paris et ses 14 lignes, par exemple ?

Une solution à cette problématique serait l'utilisation de marqueurs personnalisés.

Images de marqueurs

En zoomant de près, voici le marqueur "par défaut" utilisé par l'API Google Maps : marqueur-google-encadre.png

Et l'ombre lui correspondant : marqueur-google-ombre-encadre.png

L'un comme l'autre devant être des fichiers PNG, 24 bits, et porteurs de 8 bits de transparence.

Pourquoi ne pas tenter de remplacer ces marqueurs "classiques" par d'autres, personnalisés ?
Par exemple, nous pourrions utiliser le marqueur suivant (ici encore, zoomé fortement) : mon-marqueur-encadre.png

Et son ombre : marqueur-ombre-encadre.png

(Je n'ai jamais été doué pour tout ce qui est graphisme - ça se remarque, je sais ^^ )


Création d'un marqueur personnalisé

Pour utiliser une image de votre choix à la place de celle par défaut, il faut passer un second paramètre au constructeur d'objet GMarker.
Ce second paramètre doit être un objet contenant une propriété nommée "icon", qui pointera vers une instance de classe GIcon.

Autre dit, il vous faut créer une instance de classe GIcon, et renseigner les propriétés définissant votre icone :

// Ajout d'un marqueur sur la carte :
var myIcon = new GIcon();
myIcon.image = "images/mon-marqueur.png";
myIcon.shadow = "images/marqueur-ombre.png";
myIcon.iconSize = new GSize(20, 34);
myIcon.shadowSize = new GSize(40, 33);
myIcon.iconAnchor = new GPoint(10, 34);
myIcon.infoWindowAnchor = new GPoint(10, 1);
var markerOptions = {
    icon: myIcon
};
var marker = new GMarker(coord, markerOptions);  // Création d'un marqueur localisé sur ce point
map.addOverlay(marker);  // Et ajout du marqueur à la carte

Les propriétés qui nous intéressent sont les suivantes :

  • image : le chemin vers le fichier PNG/24 à utiliser pour le marqueur.
  • shadow : la même chose, mais pour le fichier PNG/24 qui sera utilisé comme ombre du marqueur. De manière générale, vous utiliserez une ombre orientée à 45° par rapport à votre marqueur.
  • iconSize, showSize : les tailles respectives, en pixels, de vos images.
  • iconAnchor : Les coordonnées du point de l'image d'ombre qui doivent correspondre à la position du marqueur
  • infoWindowAnchor : Utile pour plus tard (seconde partie de cet article) : les coordonnées qui seront utilisées pour l'affichage d'une éventuellement fenêtre d'information associée au marqueur.

La portion de code présentée ci-dessus, une fois intégrée au squelette présenté plus haut, donne la capture d'écran suivante :

carte-ex3-marqueur-perso.png

Je ne dirais pas que c'est plus joli... Mais c'est au moins plus original !


Exemple un peu plus complet d'utilisation de marqueurs personnalisés

Pour reprendre l'exemple utilisé un peu plus haut, celui des stations de métro des 4 lignes lyonnaises, voici ce que nous pourrions obtenir en travaillant avec des marqueurs personnalisés :

La méthode de création de marqueur crée, pour chaque marqueur, une instance d'objet GIcon, en utilisant une image dépendant de la ligne sur laquelle se trouve la station correspondant au marqueur en cours de création :

var createMarker = function(infosStation)
{
    var point = new GPoint(infosStation.lng, infosStation.lat);

    var myIcon = new GIcon();
    if (infosStation.ligne === 'A')
        myIcon.image = "images/marqueur-rouge.png";
    else if (infosStation.ligne === 'B')
        myIcon.image = "images/marqueur-bleu.png";
    else if (infosStation.ligne === 'C')
        myIcon.image = "images/marqueur-orange.png";
    else if (infosStation.ligne === 'D')
        myIcon.image = "images/marqueur-vert.png";
    myIcon.shadow = "images/marqueur-ombre.png";
    myIcon.iconSize = new GSize(20, 34);
    myIcon.shadowSize = new GSize(40, 33);
    myIcon.iconAnchor = new GPoint(10, 34);
    myIcon.infoWindowAnchor = new GPoint(10, 1);

    var markerOptions = {
        icon: myIcon
    };

    var marker = new GMarker(point, markerOptions);
    return marker;
}; // createMarker

Et l'affichage devient plus appréciable :

carte-ex4-plusieurs-marqueurs-perso.png

(Pour cet exemple, j'ai rajouté à la page HTML le code correspondant à la génération de la légende ; je n'entre pas dans les détails ici : il s'agit de HTML de base)

Voila comment, en quelques lignes de code, vous avez rendu votre carte plus attrayante - et plus facile à comprendre et à exploiter par les visiteurs de votre site !


Utiliser l'outil "MapIconMaker" pour créer rapidement des marqueurs personnalisés

Les exemples précédents nous ont montré comment utiliser des images personnalisées pour nos marqueurs.

Mais, si ce que vous recherchez est - comme moi lors de mon dernier exemple - uniquement des marqueurs de couleurs différentes, vous n'avez pas besoin de vous compliquer la tâche en créant des images différentes pour chaque marqueur !

En réponse à cette problématique, vous trouverez dans la Bibliothèque d'utilitaires Google Maps un composant nommé MapIconMaker (anciennement nommé "IconFactory" - c'était le cas au moment où j'ai écrit les exemples accompagnant cet article, notamment).
Vous trouverez le post d'annonce sur le Blog officiel de Google Maps : MapIconMaker.

Ce composant permet de créer des icônes personnalisés, en spécifiant uniquement

  • leur taille
  • et leur couleur.

Il se charge de toute leur création - en se basant sur le marqueur "standard" de l'API Google Maps.

Par exemple, nous pourrions utiliser ce composant de la manière suivante :

var createMarker = function(infosStation)
{
    var point = new GPoint(infosStation.lng, infosStation.lat);

    var color;
    if (infosStation.ligne === 'A')
        color = 'ed1c24';
    else if (infosStation.ligne === 'B')
        color = '05a1e6';
    else if (infosStation.ligne === 'C')
        color = 'fab41d';
    else //if (infosStation.ligne === 'D')
        color = '00a650';

    var myIcon = MapIconMaker.createMarkerIcon({width: 36, height: 32, primaryColor: color});

    var markerOptions = {
        icon: myIcon
    };

    var marker = new GMarker(point, markerOptions);
    return marker;
}; // createMarker

Pour la création de chaque marqueur, et la portion de code suivante pour itérer sur la liste des stations :

// Ajout d'un marqueur pour chacune des stations de metro de Lyon
for (var i=0 ; i<stationsMetro.length ; i++)
{
    map.addOverlay(createMarker(stationsMetro[i]));
}

La méthode createMarkerIcon prend en paramètre un objet définissant

  • width : la largeur du marqueur,
  • height : la hauteur du marqueur,
  • et primaryColor : la couleur de base du marqueur, le marqueur lui-même étant créé avec un effet de reflet lumineux.

Pour notre exemple, plutôt que de spécifier une image différente pour chaque ligne de métro, nous n'avons plus eu qu'à spécifier la couleur de la ligne !

Ce qui donne comme résultat l'effet reproduit sur la capture ci-dessous :

carte-ex5-IconFactory.createMarkerIcon.png

Plutôt satisfaisant, non ?

  • Pas besoin de créer de nouveaux marqueur - ne répondant pas forcément aux habitudes des utilisateurs (forme, ombre, ...)
  • Pas de marqueurs "moches" - enfin, là, ça dépend de votre graphiste ;-)
  • Et différenciation des différentes lignes de métro - comme précédemment !


Un peu de fun avec les marqueurs

"Just for fun", vous pouvez imaginer aller plus loin avec vos marqueurs sur la carte !

Notamment, vous pouvez souhaiter n'en n'afficher certains que lorsque l'utilisateur a zoomé de suffisamment près, l'intérêt étant d'éviter de surcharger la carte lorsque l'on se trouve en vue lointaine.

En appliquant cette idée à nos exemples de lignes de métro, j'en suis arrivé au schéma suivant :

  • Quelque soit le niveau de zoom, on affiche les quatre lignes de métro,
  • Et si l'utilisateur zoome suffisament, on affiche en plus les trois lignes de tramway - avec des marqueurs plus petit (et on les masquera lorsque l'utilisateur dé-zommera)
  • Le tout, pour simplifier les choses, en utilisant le composant MapIconMaker.

Pour cela, il nous faut modifier notre définition des lignes de métro/tram, pour ajouter un niveau de zoom "minimal" :

// Liste des stations de metro de Lyon
var stationsMetro = [
    // Lignes de Metro

    {ligne: 'A', loc: 'L. Bonnevay Astroballe', lat: 45.76434960130271, lng: 4.91063117980957, zoomMin: 0},
    {ligne: 'A', loc: 'Cusset', lat: 45.76482861073421, lng: 4.901275634765625, zoomMin: 0},

    {ligne: 'B', loc: 'Charpennes - Charles Hernu', lat: 45.77021718342828, lng: 4.86393928527832, zoomMin: 0},
    {ligne: 'B', loc: 'Brotteaux', lat: 45.76692422863731, lng: 4.860076904296875, zoomMin: 0},

    {ligne: 'C', loc: 'Cuire', lat: 45.7850630013786, lng: 4.8332977294921875, zoomMin: 0},
    {ligne: 'C', loc: 'Henon', lat: 45.77907726002176, lng: 4.827632904052734, zoomMin: 0},

    {ligne: 'D', loc: 'Gare de Vaise', lat: 45.77955614297965, lng: 4.804630279541016, zoomMin: 0},
    {ligne: 'D', loc: 'Valmy', lat: 45.77464739768229, lng: 4.806003570556641, zoomMin: 0},

    // Lignes de Tramway

    {ligne: 'T1', loc: '', lat: 45.740656892848875, lng: 4.8190659284591675, zoomMin: 13},
    {ligne: 'T1', loc: '', lat: 45.73942889120833, lng: 4.818025231361389, zoomMin: 13},

    {ligne: 'T2', loc: '', lat: 45.74896297821371, lng: 4.826200604438782, zoomMin: 13},
    {ligne: 'T2', loc: '', lat: 45.74705666541551, lng: 4.8362937569618225, zoomMin: 13},


    {ligne: 'T3', loc: '', lat: 45.76024885029971, lng: 4.861934334039688, zoomMin: 13},
    {ligne: 'T3', loc: '', lat: 45.752935423810314, lng: 4.868786036968231, zoomMin: 13}

]; // stationsMetro

(Ici encore, vous trouverez la liste complète dans l'archive d'exemples jointe à cet article)

Pour ce qui est de la créations des marqueurs, quelques améliorations / différences :

var createMarker = function(infosStation, zoomLevel)
{
    var point = new GPoint(infosStation.lng, infosStation.lat);

    var color = 'FFFFFF';
    var width=32, height=32;
    if (infosStation.ligne.length === 1) {
        if (infosStation.ligne === 'A')
            color = 'ed1c24';
        else if (infosStation.ligne === 'B')
            color = '05a1e6';
        else if (infosStation.ligne === 'C')
            color = 'fab41d';
        else if (infosStation.ligne === 'D')
            color = '00a650';
        width = 36;
        height = 32;
    }
    else {
        if (infosStation.ligne === 'T1')
            color = '005e8a';
        else if (infosStation.ligne === 'T2')
            color = '0f612f';
        else if (infosStation.ligne === 'T3')
            color = '00aaa9';
        width = 26;
        height = 22;
    }

    var myIcon = IconFactory.createMarkerIcon({width: width, height: height, primaryColor: color});

    var markerOptions = {
        icon: myIcon
    };

    var marker = new GMarker(point, markerOptions);

    marker.autoShowHide = function(zoom){
        if (zoom >= infosStation.zoomMin) {
            marker.show();
        }
        else {
            marker.hide();
        }
    };

    return marker;
}; // createMarker

Tout d'abord, nous tenons compte des lignes de Tramways pour les affectations de couleurs, puis nous affectons à chaque marqueur une méthode qui l'affichera ou le masquera en fonction du niveau de zoom.

Ensuite, nous créons chaque marqueur :

// Ajout d'un marqueur pour chacune des stations de metro de Lyon
for (var i=0 ; i<stationsMetro.length ; i++)
{
    marker = createMarker(stationsMetro[i], map.getZoom());
    markers.push(marker);
    map.addOverlay(marker);

    marker.autoShowHide(map.getZoom());
}

Sans oublier de l'afficher ou de le masquer en fonction du niveau de zoom de départ.

Et, pour finir, nous ajoutons à la carte un gestionnaire d'événement, branché sur l'événement levé en fin d'opération de zoom :

GEvent.addListener(map, "zoomend", function(oldLevel, newLevel) {
    for (var i = 0; i < markers.length; i++) {
        markers[i].autoShowHide(newLevel);
    }
});

Ceci signifie qu'à chaque fois que l'utilisateur viendra de (dé-)zoomer, la méthode d'affichage / de masquage sera appelée pour chaque marqueur.

Note : Nous en verrons probablement plus au sujet des événements au sein d'un futur article ; je ne rentrerai pas dans les détails ici.

Et voila la carte obtenu : en vue "lointaine" :

carte-ex6-zoom-loin-metro.png

Et en zoomant, les stations des trois lignes de tramway apparaissent :

carte-ex6-zoom-pres-metro-tram.png

Cette idée peut éventuellement apporter quelque chose aux utilisateurs de votre site ? Pourquoi pas ? A vous de voir !


Afficher une miniature de la carte autour d'un marqueur : showMapBlowup

Avant de terminer cette première partie traitant des marqueurs affichables sur une Google Map, et pour faire transition avec la seconde parlant des fenêtres d'informations, voici une fonctionnalité que propose l'API Google Maps pour les marqueurs.

Vous avez la possibilité de provoquer l'affichage d'une "mini-map" lors du clic sur un marqueur. Pour cela, il faut brancher une fonction sur le gestionnaire d'événement "click" dudit marqueur.

Cette fonction sera chargée d'appeler la méthode showMapBlowup exportée par le marqueur :

// Ajout d'un premier marqueur : cliquer dessus provoquera l'affichage d'une mini-map
var marker = new GMarker(coord);
GEvent.addListener(marker, "click", function(){
    marker.showMapBlowup({
            zoomLevel: map.getZoom() - 2,
            mapType: G_NORMAL_MAP
        });
});
map.addOverlay(marker);

// Et ajout d'un second marqueur, pour voir s'il apparait sur la mini-map
var point2 = new GPoint(4.844112396240234, 45.760337735846626);
var marker2 = new GMarker(point2);
map.addOverlay(marker2);

La méthode showMapBlowup de la classe GMarker prend en paramètre un objet définissant l'affichage qui sera utilisé pour la "mini-map" lors de son ouverture.
Celui-ci peut en particulier être porteur des deux propriétés suivantes :

  • zoomLevel : le niveau de zoom auquel sera affichée la mini-map ; à vous de voir si vous préférez un zoom plus rapproché (pour avoir un aperçu du détail du lieu environnant le marqueur), ou au contraire, plus éloigné (pour situer le lieu sur une carte plus "grande").
  • mapType : Le type de carte à afficher lors de l'ouverture de la mini-map.

En l'occurence, avec la portion de code reproduite ci-dessus, voici le rendu obtenu :

carte-ex7-marker-showMapBlowup.png

Comme indiqué plus haut, l'utilité principale étant de permettre à vos utilisateurs de mieux situer un lieu ; par exemple, ici, la mini-map permet de mieux situer la Place Bellecour dans Lyon, tout en conservant une vue assez rapprochée pour la carte principale.


Google Maps et fenêtres d'informations

Maintenant que nous savons comment ajouter des marqueurs sur une carte Google Maps, nous allons voir comment les rendre plus utiles.
Plus précisément, nous verrons quels différents types de fenêtres d'informations il est possible d'associer à un marqueur, de manière à présenter plus de données à l'utilisateur cliquant sur l'un d'entre eux.

Le principe de base pour l'affichage d'une fenêtre d'informations est le suivant :

  • Création d'un marqueur,
  • Création d'une fonction ouvrant une fenêtre d'informations sur un marqueur,
  • Et association de cette fonction à un événement déclenché sur le marqueur - typiquement, un clic sur celui-ci.


Fenêtre d'informations simple

Le premier type de fenêtre d'information proposé par Google Maps est un simple affichage de données au format HTML.

Une fenêtre de ce type est ouverte à l'aide de la méthode openInfoWindowHtml de la classe GMarker :

var marker = new GMarker(coord);

var window = function() {
    marker.openInfoWindowHtml(
            '<strong>Place Bellecour</strong>' +
            '<br /><img src="images/place-bellecour-miniature.jpg" alt="" />' +
            '<br /><a href="http://fr.wikipedia.org/wiki/Place_Bellecour">Voir l\'article sur Wikipedia (fr)</a>'
      );
};

GEvent.addListener(marker, "click", window);

map.addOverlay(marker);

On retrouve ici les étapes que je décrivais juste au-dessus :

  • On commence par instancier un marqueur,
  • Puis on déclare une fonction ouvrant une fenêtre d'information rattachée à ce marqueur,
  • Fonction que l'on rattache au clic sur ledit marqueur,
  • Et, enfin, on ajoute le marqueur à la carte.

Et voici le rendu obtenu lors du clic sur notre marqueur :

carte-ex-win1-openInfoWindowHtml.png

On constate bien que les éléments HTML ont été affichés - je pense notamment à l'image et à l'hyperlien.


Fenêtre d'informations multi-onglets

Une fois que l'on a commencé à afficher des informations lors du clic sur un marqueur, on se rend compte que la fenêtre proposée n'est pas assez grande... Fidèle au concept "multi-tab" utilisé par tous les navigateurs modernes, l'API Google Maps permet d'ouvrir une fenêtre d'informations... à plusieurs onglets !

Ceci se fait à l'aide de la méthode openInfoWindowTabsHtml de la classe GMarker, qui prend en paramètre une liste d'instances d'objet GInfoWindowTab.

Chacun de ces objets GInfoWindowTab est construit à l'aide de deux paramètres :

  • le titre de l'onglet,
  • et son contenu - au format HTML.

Par exemple, pour une fenêtre d'informations à deux onglets :

var marker = new GMarker(coord);

var window = function() {
    var tabs = [
            new GInfoWindowTab('Infos',
                    '<strong>Place Bellecour</strong>' +
                    '<br /><img src="images/place-bellecour-miniature.jpg" alt="" />' +
                    '<br /><a href="http://fr.wikipedia.org/wiki/Place_Bellecour">Voir l\'article sur Wikipedia (fr)</a>'
                ),
            new GInfoWindowTab('Metro',
                    'Metro A' +
                    '<br />Metro D'
                )
            ];

	marker.openInfoWindowTabsHtml(tabs);
};
GEvent.addListener(marker, "click", window);

map.addOverlay(marker);

Le principe reste le même que pour l'exemple précédent, où la fenêtre d'informations ne comportait pas d'onglets : on ne relève que deux différences :

  • Il faut créer les deux onglets,
  • Et l'emploi de la méthode openInfoWindowTabsHtml à la place de openInfoWindowHtml

En exécutant ce code (encore une fois, après intégration au squelette proposé en tête d'article), on obtient, selon l'onglet sélectionné, l'une des deux captures d'écran suivantes :

carte-ex-win2-openInfoWindowTabsHtml.png

Pour le premier onglet, et ceci pour le second :

carte-ex-win2-openInfoWindowTabsHtml-2.png

Notez tout de même qu'il vaut mieux ne pas abuser de ces fonctionnalités, sous peine que vos utilisateurs ne soient perdus...


Fenêtre d'informations maximisable

Et si vous n'avez toujours pas assez de place pour afficher vos informations avec une fenêtre multi-onglet, en particulier dans le cas où vous souhaitez afficher un grand texte informatif, vous avez la possibilité de rendre votre fenêtre maximisable.

Une fenêtre maximisée prendra la taille de la carte entière, ce qui vous offrira plus de surface pour afficher des information.
Notez que la fenêtre affichée en mode maximisée présente des informations qui sont spécifiques à ce mode, et plus les onglets qu'elle affiche en conditions normales.

Pour rendre une fenêtre maximisable, il faut passer en second paramètre à la fonction d'ouverture de fenêtre (openInfoWindowHtml ou openInfoWindowTabsHtml) un objet contenant les deux propriétés suivantes :

  • maxTitle : le titre que portera la fenêtre une fois maximisée,
  • et maxContent : le contenu (au format HTML) qui sera affiché au sein de la fenêtre, une fois celle-ci maximisée.

Par exemple, pour afficher un long texte explicatif sur la fenêtre utilisée pour les exemples précédents :

var marker = new GMarker(coord);

var window = function() {
    var tabs = [
            new GInfoWindowTab('Infos',
                    '<strong>Place Bellecour</strong>' +
                    '<br /><img src="images/place-bellecour-miniature.jpg" alt="" />' +
                    '<br /><a href="http://fr.wikipedia.org/wiki/Place_Bellecour">Voir l\'article sur Wikipedia (fr)</a>'
               ),
            new GInfoWindowTab('Metro',
                    'Metro A' +
                    '<br />Metro D'
               )
        ];
    var options = {
        maxTitle: 'Place Bellecour, Lyon : Détails',

        maxContent: '<p><br />' +
                'La <b>place Bellecour</b> est la plus grande place de <a href="http://fr.wikipedia.org/wiki/Lyon" title="Lyon">Lyon</a> et ' +
                'la troisième plus grande place de <a href="http://fr.wikipedia.org/wiki/France" title="France">France</a> ' +
                '(après la <a href="http://fr.wikipedia.org/wiki/Place_des_Quinconces" title="Place des Quinconces">place des Quinconces</a> à ' +
                '<a href="http://fr.wikipedia.org/wiki/Bordeaux" title="Bordeaux">Bordeaux</a> et la <a href="http://fr.wikipedia.org/wiki/Place_de_la_Concorde" title="Place de la Concorde">place de la Concorde</a> ' +
                'à <a href="http://fr.wikipedia.org/wiki/Paris" title="Paris">Paris</a>), ' +
                'et avec une taille de 310 mètres par 200 mètres (elle est donc plus grande que le Zocalo de Mexico 230x192 et que la Place Rouge de Moscou 330x70). ' +
                'C\'est également <b>la plus grande place piétonne d\'Europe</b>, les places précédemment citées pouvant accueillir des véhicules, ' +
                'au contraire de la Place Bellecour.</p>' +
                '<p>En son centre se trouve une <a href="http://fr.wikipedia.org/wiki/Statue_%C3%A9questre" title="Statue équestre">statue équestre</a> de Louis XIV. ' +
                'Une autre statue, représentant le <a href="http://fr.wikipedia.org/wiki/Petit_Prince" class="mw-redirect" title="Petit Prince">Petit Prince</a> ' +
                'et <a href="http://fr.wikipedia.org/wiki/Antoine_de_Saint-Exup%C3%A9ry" title="Antoine de Saint-Exupéry">Antoine de Saint-Exupéry</a>, ' +
                'est située à l\'extrémité ouest de la place.</p>' +
                '<p>Deux pavillons se trouvent également sur la place. Le premier abrite l\'Office du Tourisme, le second une galerie d\'art.</p>'
        };
    marker.openInfoWindowTabsHtml(tabs, options);
};
GEvent.addListener(marker, "click", window);

map.addOverlay(marker);

Vous remarquerez l'apparition d'un bouton permettant de maximiser la fenêtre, en haut à droite de celle-ci :

carte-ex-win3-max-closed.png

Et une fois ce bouton cliqué :

carte-ex-win3-max-opened.png

Le bouton en haut à droite de la fenêtre se transforme, pour permettre de re-basculer vers le mode d'affichage normal.

Note : Si votre application est destinée à des utilisateurs avancés et/ou avertis, cette fonctionnalité vous servira peut-être. Par contre, dans le cas où votre application vise un public plus large, demandez-vous si elle sera utilisée par vos visiteurs : est-ce que ceux-ci ne finiront pas par être perdus au milieu de cet étalage technologique ?


Fenêtre d'informations avec styles CSS

Nous voici presque arrivés à la fin de cet article, et je réalise que les fenêtres d'informations que je vous ai présenté tout au long de celui-ci étaient graphiquement pauvre : aucune d'entre elles n'utilisait de fonctionnalités de mise en page par feuille de style CSS !

Heureusement, sela ne signifie pas que ce n'est pas possible !

Si vous définissez des styles au sein de votre page, que ce soit dans la partie <head> de la page (comme dans l'exemple ci-dessous), ou au sein d'une feuille de styles CSS externe, vous pourrez l'utiliser dans les textes de votre fenêtre d'information.

Par exemple, définissons deux styles (simples) au sein de la balise <head> de notre page :

<style type="text/css">
    #metroA {
        color: #ed1c24;
        font-weight: bold;
    }
    #metroD {
        color: #00a650;
        font-style: italic;
    }
</style>

Et utilisons les dans le second onglet de notre exemple - ici, pour afficher les couleurs des deux stations de Metro passant Place Bellecour :

var marker = new GMarker(coord);
var window = function() {
    var tabs = [
            new GInfoWindowTab('Infos',
                    '<strong>Place Bellecour</strong>' +
                    '<br /><img src="images/place-bellecour-miniature.jpg" alt="" />' +
                    '<br /><a href="http://fr.wikipedia.org/wiki/Place_Bellecour">Voir l\'article sur Wikipedia (fr)</a>'
               ),
            new GInfoWindowTab('Metro',
                    '<span id="metroA">Metro A</span>' +
                    '<br /><span id="metroD">Metro D</span>'
               )
        ];

    marker.openInfoWindowTabsHtml(tabs);
};
GEvent.addListener(marker, "click", window);
map.addOverlay(marker);

Et voici une capture d'écran du rendu obtenu :

carte-ex-win2-style-css.png

Comme nous pouvons le constater, nos styles ont bien été pris en compte à l'intérieur de la fenêtre d'informations :-)


Navigation :