Problème: des événements de l’API Google Maps v3 comme bounds_changed, zoom_changed, idle
se déclenchent à chaque exécution de la méthode fitBounds
qui permet d’ajuster automatiquement le zoom de la carte afin que celle-ci affiche l’ensemble des markers de la map.
MAIS… comme très souvent remonté (ici et là par exemple), l’exécution de la méthode fitBounds
, incontournable si on souhaite afficher tous les markers disponibles sur la carte dans le viewport, va très logiquement déclencher les événements code>bounds_changed, zoom_changed, idle, puisqu’elle va faire « bouger » la carte lorsqu’elle va zoomer ou dézoomer. Si votre fonction fitBounds
est exécutée au délenchement d’un des événements pré-cités, vous entrez dans une boucle infinie: l’exécution de fitBounds recommence encore er encore jusqu’à faire crasher le navigateur.
Solution: faire un mix de ce qui est suggéré ici: Do not fire ‘zoom_changed’ event when calling fitBounds function on map et ici: Fire javascript function 2 sec after no activity in input tag.
Créer un flag qui n’autorise pas les événements de la map à être exécutés si il est assigné (comme par défaut) à false
.
1 |
let allowMapEventsToBeFired = false; |
Mettre en place un premier timer
avec un seuil de 2 secondes qui se remettra à zéro et recommencera à chronométrer à chaque fois que l’event sera déclenché. Tant que ce timer n’aura pas atteint 2 secondes, il empêchera l’événement (bounds_changed
dans notre exemple) de se déclencher réellement parce que le flag restera à false
. Ce qu’on cherche ici, c’est d’éviter qu’en cas de boucle, le code assigné au déclenchement de l’événement ne soit exécuté encore et encore et encore…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
let timer; let timer2; function onInput() { clearTimeout(timer); clearTimeout(timer2); timer = setTimeout(function(){ mapOperator.allowMapEventsToBeFired = true }, 1999); if ( mapOperator.allowMapEventsToBeFired === false ) { console.log('mapOperator.allowMapEventsToBeFired: ', mapOperator.allowMapEventsToBeFired); return false; } else if ( mapOperator.allowMapEventsToBeFired ) { console.log('mapOperator.allowMapEventsToBeFired: ', mapOperator.allowMapEventsToBeFired); timer2 = setTimeout(mapOperator.topic_updatesOnBoundsChanged.bind(this), 1000); } } google.maps.event.addListener(mapApi.mapObj, 'bounds_changed', onInput, false); |
1 2 3 4 5 6 7 8 9 |
function topic_updatesOnBoundsChanged() { // [TODO] vérifier si il y a de nouveau markers à afficher? /* On affiche/masque le bouton refreshMap */ utils.toggleElementVisibility(refreshMap.$refreshMapButton); /* au click sur le bouton refreshMap: relancer le bordel */ refreshMap.$refreshMapButton.addEventListener('click', mapOperator.topic_updatesOnMapEvents); } |