Gestion des événements event dans l'API Google Maps JavaScript V3

Documentation exemples et tutoriels en Français

API Google Maps JavaScript version 3

Vue d'ensemble

Javascript est un langage événementiel, cela signifie que Javascript répond aux interactions en générant des événements et prévoit un programme pour écouter les événements intéressants.

Le modèle événementiel pour l'API Google Maps version 3 est similaire à celui utilisé dans la version 2, même si beaucoup de choses ont changé.

  • les événements utilisateur (tel que l'événement cick d'une souris) sont propagés du DOM vers l'API Google Maps. Ces événements sont séparés et distincts des événements DOM standards.
  • les notifications de changement d'état MVC reflètent les changements dans les objets de l'API Google Maps et sont nommés en utilisant la convention nomdelapropriété_changed

Chaque objet de l'API Google Maps exporte un certain nombre d'événements nommés. Les programmes interessés par certains événements enregistrent les auditeurs d'événements Javascript de ces événements et executent du code lorsque ces événements sont reçus par le gestionnaire d'événements addListener() dans l'espace de nommage google.maps.event.

Pour la liste complète des événements consultez la référence de l'API Google Maps V3. Pour chaque objet contenant des événements, les événements sont listés dans une section indépendante.

Exemples :

Les événements de l'interface utilisateur

Certains objets dans l'API Google Maps V3 sont conçus pour répondre aux événements utilisateurs tels que les événements clavier ou souris. Un objet google.maps.Maker peut écouter les événements utilisateur suivants :

Ces événements peuvent ressembler à des événements DOM standards, mais ils font partie intégrante de l'API Google Maps V3. Étant donné que les divers navigateurs mettent en place différents modèles d'événements DOM, l'API Google Maps V3 fournit ces mécanismes pour écouter et répondre aux événements DOM sans avoir à gérer les particularités liées aux différents navigateurs. Ces événements passent généralement des arguements au sein de l'événement précisant l'état de l'interface utilisateur (exemple : position de la souris).

Les changements d'état MVC

Les objets MVC contiennent typiquement un état. Chaque fois que la propriété d'un objet change, l'API déclenche un événement indiquant que la propriété a été modifiée. Par exemple, l'API déclenchera un événement zoom_changed sur la carte lorsque le niveau de zoom de la carte est modifié. Vous pouvez intercepter ces changements d'état en utilisant le gestionnaire d'événements addListener() comme méthode de l'espace de nommage google.maps.event

Les événements utilisateur et changements d'état MVC peuvent sembler similaires, mais généralement vous souhaitez les traiter différemment dans votre code. Les événements MVC, par exemple, ne transmettent pas d'arguments dans leur événement. Vous devrez inspecter la propriété changée sur un changement d'état MVC en appelant la méthode appropriée getNomdelapropriete.

Événements carte

L'enregistrement des notifications d'événements se fait à l'aide de la méthode addListener(). Cette méthode prend en paramètre :

  • un objet,
  • un événement à surveiller,
  • une fonction à appeler lorsque l'événement spécifié se produit.

Le code suivant mélange les événements utilisateur avec des événements liés au changement d'état. Nous attachons un gestionnaire d'événements à un marqueur qui zoom sur la carte lorsque vous cliquez dessus. Nous avons également ajouté un gestionnaire d'événements à la carte pour les modifications de la propriété center et déplacer la carte vers le marqueur 3 secondes après la réception de l'événement center_changed.

<!DOCTYPE html>
<html>
	<head>
		<title>Titre de votre page</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
		<meta charset="utf-8">
		<style type="text/css">
			html, body {
				height: 100%;
				margin: 0;
				padding: 0;
			}
			#EmplacementDeMaCarte {
				height: 100%;
			}
		</style>
		<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
		<script>
			function initialisation() {
				/*
				 * Options pour la carte
				 */
				var optionsCarte = {
					zoom: 4,
					center: new google.maps.LatLng(47.389982, 0.688877),
					mapTypeId: google.maps.MapTypeId.ROADMAP
				};
				/*
				 * Création d'une carte nommée 'maCarte'
				 */
				var maCarte = new google.maps.Map(document.getElementById('EmplacementDeMaCarte'), optionsCarte);

				/*
				 * Création d'un marqueur nommé 'monMarqueur'
				 * positionné au centre de la carte nommée 'maCarte'
				 */
				var monMarqueur = new google.maps.Marker({
					position: maCarte.getCenter(),
					map: maCarte,
					title: 'Ciquez pour zoomer'
				});
				/*
				 * Gestionnaire événement MVC.
				 * Tout changement du centre de la carte nommée 'maCarte'
				 * déclenchera au bout 3 secondes le déplacement de la 
				 * carte nommée 'maCarte' pour que son centre coïncide
				 * avec la position du marqueur nommé 'monMarqueur'
				 */
				google.maps.event.addListener(maCarte, 'center_changed', function() {
					window.setTimeout(function() {
						maCarte.panTo(monMarqueur.getPosition());
					}, 3000);
				});
				/*
				 * Gestionnaire événement utilisateur.
				 * Tout 'click' sur le marqueur nommée 'monMarqueur'
				 * va déclencher :
				 * - un zoom de niveau 8 sur la carte nommée 'maCarte'
				 * - centrer la carte nommée 'maCarte' sur la postion
				 *   actuelle du marqueur nommé 'monMarqueur'
				 */
				google.maps.event.addListener(monMarqueur, 'click', function() {
					maCarte.setZoom(8);
					maCarte.setCenter(monMarqueur.getPosition());
				});
			}
			google.maps.event.addDomListener(window, 'load', initialisation);
		</script>
	</head>
	<body>
		<div id="EmplacementDeMaCarte"></div>
	</body>
</html>

Astuce :

Si vous essayez de détecter un changement dans la fenêtre d'affichage, assurez-vous d'utiliser l'événement spécifique bounds_changed plutôt que les événements constitutifs zoom_changed et center_changed. Parce que l'API Google Maps Javascript V3 déclenche ces derniers événements de façon indépendante, getBounds() ne peut retourner les résultats escomptés qu'après que la zone d'affichage ait été modifiée avec autorité. Si vous souhaitez obtenir les limites getBounds() après un tel événement, nous vous invitons à écouter à la place l'événement bounds_changed.

Accéder aux arguments des événements de l'interface utilisateur

Les événements de l'interface utilisateur au sein de l'API Google Maps Javascript V3 passent généralement un argument d'événement qui peut être consulté par l'observateur d'événement, soulignant l'état de l'interface utilisateur lorsque l'événement s'est produit. Par exemple, un événement 'click' de l'interface utilisateur passe généralement un MouseEvent contenant une propriété latLng indiquant les coordonnées de l'emplacement cliqué sur la carte. Notez que ce comportement est uniquement lié aux événements de l'interface utilisateur. Les changements d'état MVC ne passent aucun argument dans leur événements.

Vous pouvez accéder aux arguments de l'événement au sein d'un observateur d'événement de la même façon que vous accédez aux propriétés d'un objet. L'exemple suivant ajoute un observateur d'événement à la carte, et crée un marqueur lorsque l'utilisateur clique sur la carte, à l'emplacement cliqué

<!DOCTYPE html>
<html>
	<head>
		<title>Titre de votre page</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
		<meta charset="utf-8">
		<style type="text/css">
			html, body {
				height: 100%;
				margin: 0;
				padding: 0;
			}
			#EmplacementDeMaCarte {
				height: 100%;
			}
		</style>
		<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
		<script>
			function initialisation() {
				/*
				 * Options pour la carte
				 */
				var optionsCarte = {
					zoom: 4,
					center: new google.maps.LatLng(47.389982, 0.688877),
					mapTypeId: google.maps.MapTypeId.ROADMAP
				};
				/*
				 * Création d'une carte nommée 'maCarte'
				 */
				var maCarte = new google.maps.Map(document.getElementById('EmplacementDeMaCarte'), optionsCarte);

				/*
				 * Gestionnaire événement utilisateur.
				 * Tout 'click' sur la carte nommée 'maCarte'
				 * va déclencher l'appel de 'positionnerMarqueur'
				 * en lui transmettant en paramètre :
				 * - Les latitude / longitude situées en dessous
				 *   du curseur lorsque l'événement s'est produit
				 * - la carte nommée 'maCarte'
				 */
				google.maps.event.addListener(maCarte, 'click', function(evenement) {
					positionnerMarqueur(evenement.latLng, maCarte);
				});
			}
				
			function positionnerMarqueur(position, carte) {
				var monMarqueur = new google.maps.Marker({
					position: position,
					map: carte
				});
				carte.panTo(position);
			}
			
			google.maps.event.addDomListener(window, 'load', initialisation);
		</script>
	</head>
	<body>
		<div id="EmplacementDeMaCarte"></div>
	</body>
</html>

Utilisation des closures dans le gestionnaire d'événements

Lors de l'execution d'un gestionnaire d'événements, il est souvent avantageux d'obtenir des données à la fois privées et persistantes rattachées à un objet. Javascript ne supporte pas les données privées instanciées, mais il supporte les closures (ou fermetures) qui permettent à des fonctions internes d'accéder à des variables externes. Les closures sont utiles dans les gestionnaires d'événements pour accéder aux variables normalement non attachées aux objets sur lesquels les événements se produisent.

L'exemple ci-dessous utilise une closure (ou fermeture) sous forme de fonction dans l'observateur d'événement pour affecter un message secret à un ensemble de marqueurs. En cliquant sur chaque marqueur une portion du message secret, qui n'est pas contenue dans le marqueur lui-même, sera extraite et affichée.

<!DOCTYPE html>
<html>
	<head>
		<title>Titre de votre page</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
		<meta charset="utf-8">
		<style type="text/css">
			html, body {
				height: 100%;
				margin: 0;
				padding: 0;
			}
			#EmplacementDeMaCarte {
				height: 100%;
			}
		</style>
		<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
		<script>
			var maCarte;
			function initialisation() {
				/*
				 * Options pour la carte
				 */
				var optionsCarte = {
					zoom: 4,
					center: new google.maps.LatLng(47.389982, 0.688877),
					mapTypeId: google.maps.MapTypeId.ROADMAP
				};
				/*
				 * Création d'une carte nommée 'maCarte'
				 */
				maCarte = new google.maps.Map(document.getElementById('EmplacementDeMaCarte'), optionsCarte);

				/**
				 * Ajoute 5 marqueurs sur la carte de façon aléatoire
				 */
				var limiteSudOuest = new google.maps.LatLng(34.151590,-31.171474);
				var limiteNordEst = new google.maps.LatLng(57.978254,32.549228);
				var limites = new google.maps.LatLngBounds(limiteSudOuest ,limiteNordEst);
				maCarte.fitBounds(limites);
				var lngSpan = limiteNordEst.lng() - limiteSudOuest.lng();
				var latSpan = limiteNordEst.lat() - limiteSudOuest.lat();
				for (var i = 0; i < 5; i++) {
					var emplacement = new google.maps.LatLng(limiteSudOuest.lat() + latSpan * Math.random(), limiteSudOuest.lng() + lngSpan * Math.random());
					var monMarqueur = new google.maps.Marker({
						position: emplacement,
						map: maCarte
					});
					var j = i + 1;
					monMarqueur.setTitle(j.toString());
					attacherMessageSecret(monMarqueur, i);
				}
			}

			/**
			 * Les 5 marqueurs affichent un message secret lorsqu'ils sont cliqués
			 * mais ce message n'est pas présent dans l'instance du marqueur
			 */
			function attacherMessageSecret(marqueur, nombre) {
				var message = ["Ceci","est","le","message","secret"];
				var infoBulle = new google.maps.InfoWindow({
					content: message[nombre],
					size: new google.maps.Size(50,50)
				});
				google.maps.event.addListener(marqueur, 'click', function() {
					infoBulle.open(maCarte, marqueur);
				});
			}

			google.maps.event.addDomListener(window, 'load', initialisation);
		</script>
	</head>
	<body>
		<div id="EmplacementDeMaCarte"></div>
	</body>
</html>

Obtention et définition des propriétés dans les gestionnaires d'événements

Aucun des événements de changement d'état MVC dans le système événementiel de l'API Google Maps V3 ne passe d'arguments lorsque l'événement est déclenché. Alors que les événements utilisateur passent des arguments qui peuvent être traités. Si vous avez besoin d'inspecter une propriété sur un changement d'état MVC, vous devez appeler explicitement la méthode appropriée getNomdelapropriété() sur l'objet. Ce contrôle permettra de toujours récupérer l'état actuel de l'objet MVC, qui peut être différent de l'état lorsque l'événement a été déclenché initialement.

Remarque :

La définition explicite d'une propriété dans un gestionnaire d'événements qui répond à un changement d'état de cette propriété particulière, peut produire des comportements imprévisibles ou non désirés. La définition d'une telle propriété déclenche un nouvel événement, par exemple, et si vous définissez toujours une propriété dans ce gestionnaire d'événements, vous finirez par créer une boucle infinie.

Dans l'exemple ci-dessous, nous avons mis en place un gestionnaire d'événements pour répondre aux événements zoom, en ouvrant une fenêtre d'information affichant le niveau de zoom actuel.

<!DOCTYPE html>
<html>
	<head>
		<title>Titre de votre page</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
		<meta charset="utf-8">
		<style type="text/css">
			html, body {
				height: 100%;
				margin: 0;
				padding: 0;
			}
			#EmplacementDeMaCarte {
				height: 100%;
			}
		</style>
		<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
		<script>
			function initialisation() {
				var pointCentral = new google.maps.LatLng(47.389982, 0.688877);
				/*
				 * Options pour la carte
				 */
				var optionsCarte = {
					zoom: 4,
					center: pointCentral,
					mapTypeId: google.maps.MapTypeId.ROADMAP
				};
				/*
				 * Création d'une carte nommée 'maCarte'
				 */
				var maCarte = new google.maps.Map(document.getElementById('EmplacementDeMaCarte'), optionsCarte);

				/**
				 * Création de l'infowindow nommée 'infoBulle'
				 */
				var infoBulle = new google.maps.InfoWindow({
					content: 'Changer le niveau de zoom',
					position: pointCentral
				});
				infoBulle.open(maCarte);


				/**
				 * Gestionnaire événement MVC.
				 * Tout changement du niveau de zoom de la 
				 * carte nommée 'maCarte' déclenchera :
				 * - le centrage de la carte sur le point 
				 *   nommé 'pointCentral'
				 * - l'affichage du niveau de zoom actuel
				 *   dans l'infowindow nommée 'infoBulle'
				 */
				google.maps.event.addListener(maCarte, 'zoom_changed', function() {
					var niveauZoom = maCarte.getZoom();
					maCarte.setCenter(pointCentral);
					infoBulle.setContent('Niveau de Zoom : ' + niveauZoom);
				});
			}

			google.maps.event.addDomListener(window, 'load', initialisation);
		</script>
	</head>
	<body>
		<div id="EmplacementDeMaCarte"></div>
	</body>
</html>

Ecouter les événements DOM

Le modèle événementiel de l'API Google Maps V3 crée et gère ses propres événements personnalisés. Cependant le DOM (Document Object Model) dans le navigateur crée et distribue ses propres événements, selon le modèle événementiel propre au navigateur utilisé. Si vous souhaitez capturer et réagir à ces événements, l'API Google Maps fournit la méthode statique addDomListener() pour écouter et se lier aux événements DOM. L'utilisation de cette méthode à la signature suivante :

addDomListener(instance:Object, eventName:string, handler:Function)

ou l'instance peut être n'importe quel élément DOM pris en charge par le navigateur y compris :

  • les membres hiérarchiques du DOM tels que les éléments window ou document.body.monFormulaire
  • les éléments nommés tels que document.getElementById("foo")

Notez que addDomListener() passe simplement l'événement indiqué dans le navigateur, qui le gère selon son propre modèle DOM événement. Cependant, presque tous les navigateurs modernes supportent au moins le DOM niveau 2 (pour plus d'informations consultez Mozilla DOM levels reference)

Si vous avez lu cette documentation, vous êtes certainement déjà familiarisé avec un événement du DOM : l'événement window.load que nous gérons au sein de la balise <body>. Nous utilisons cet événement pour déclencher le code Javascript initial une fois que le code HTML de la page est totalement chargé, comme indiqué ci-dessous :

<!DOCTYPE html>
<html>
	<head>
		<title>Titre de votre page</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
		<meta charset="utf-8">
		<style type="text/css">
			html, body {
				height: 100%;
				margin: 0;
				padding: 0;
			}
			#EmplacementDeMaCarte {
				height: 100%;
			}
		</style>
		<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
		<script>
			function initialisation() {
				var optionsCarte = {
					zoom: 4,
					center: new google.maps.LatLng(47.389982, 0.688877),
					mapTypeId: google.maps.MapTypeId.ROADMAP
				};
				var maCarte = new google.maps.Map(document.getElementById('EmplacementDeMaCarte'), optionsCarte);
			}
		</script>
	</head>
	
	<body onload="initialisation">
		<div id="EmplacementDeMaCarte"></div>
	</body>
</html>

bien que cet événement soit attaché à la balise <body> ici, cet événement est réellement un événement window indiquant que tous les éléments hiérarchiques du DOM situés sous window ont été entiérement construits et rendus.

Bien que facile à comprendre, avoir un événement onload dans une balise <body> mélange le contenu avec le comportement. En régle générale, il est conseillé de séparer :

  • le code de contenu (HTML)
  • le code de comportement (Javacript)
  • le code de présentation (CSS)

Vous pouvez le faire en remplacant le gestionnaire d'événements en ligne onload par un auditeur DOM dans votre code Javascript comme ceci :

<!DOCTYPE html>
<html>
	<head>
		<title>Titre de votre page</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
		<meta charset="utf-8">
		<style type="text/css">
			html, body {
				height: 100%;
				margin: 0;
				padding: 0;
			}
			#EmplacementDeMaCarte {
				height: 100%;
			}
		</style>
		<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
		<script>
			function initialisation() {
				var optionsCarte = {
					zoom: 4,
					center: new google.maps.LatLng(47.389982, 0.688877),
					mapTypeId: google.maps.MapTypeId.ROADMAP
				};
				var maCarte = new google.maps.Map(document.getElementById('EmplacementDeMaCarte'), optionsCarte);
			}
			google.maps.event.addDomListener(window, 'load', initialisation);
		</script>
	</head>
	
	<body>
		<div id="EmplacementDeMaCarte"></div>
	</body>
</html>

Bien que le code ci-dessus soit du code API Maps Javascript, la méthode addDomListener() se lie à l'objet window du navigateur et permet à l'API de communiquer avec des objets situés à l'extérieur du domaine normal de l'API.