web-dev-qa-db-fra.com

Gérer les événements de clics dans Google Maps JS API v3 tout en ignorant les double-clics

Avec l'API Google Maps JS v3, je souhaite déposer un marqueur là où l'utilisateur clique sur la carte, tout en conservant le comportement par défaut lorsque l'utilisateur double-clique (et n'ajoute aucun marqueur sur la carte).

J'ai pensé à définir un délai d'expiration sur l'événement de clic. Si un événement de double clic est déclenché dans les quelques millisecondes suivantes, le délai est annulé. Sinon, le marqueur est placé sur la carte lorsque le délai expire. Mais cela ne ressemble pas vraiment à la meilleure solution de tous les temps.

Existe-t-il une manière plus élégante de gérer cela?

Merci.

46
Pierre

Le moyen le plus simple de le résoudre.

var location;
var map = ...

google.maps.event.addListener(map, 'click', function(event) {
    mapZoom = map.getZoom();
    startLocation = event.latLng;
    setTimeout(placeMarker, 600);
});

function placeMarker() {
    if(mapZoom == map.getZoom()){
        new google.maps.Marker({position: location, map: map});
    }
}

shogunpanda la solution est meilleure (voir ci-dessous)

27
rebeliagamer

Je viens de trouver une solution hackeuse qui fonctionne mais introduit un petit temps d'attente (200 ms, c'est le minimum pour le faire fonctionner, mais je ne sais pas si cela dépend du client)

var update_timeout = null;

google.maps.event.addListener(map, 'click', function(event){
    update_timeout = setTimeout(function(){
        do_something_here();
    }, 200);        
});

google.maps.event.addListener(map, 'dblclick', function(event) {       
    clearTimeout(update_timeout);
});

J'espère que cela t'aides!

62
ShogunPanda

Vous pouvez profiter des déclenchements de dblclick s'il s'agit d'un double clic et des déclenchements d'un seul clic dans de telles situations une seule fois.

runIfNotDblClick = function(fun){
    if(singleClick){
        whateverurfunctionis();
    }
};

clearSingleClick = function(fun){
    singleClick = false;
};

singleClick = false;

google.maps.event.addListener(map, 'click', function(event) {// duh! :-( google map zoom on double click!
    singleClick = true;
    setTimeout("runIfNotDblClick()", 500);
});

google.maps.event.addListener(map, 'dblclick', function(event) {// duh! :-( google map zoom on double click!
     clearSingleClick();
});

Voir http://www.ilikeplaces.com

7
Ravindranath Akila

Si vous utilisez nderscore.js ou* lodash voici un moyen rapide et élégant de résoudre ce problème

// callback is wrapped into a debounce function that is called after
// 400 ms are passed, it provides a cancel function that can be used
// to stop it before it's actually executed
var clickHandler = _.debounce(function(evt) {
  // code called on single click only, delayed by 400ms
  // adjust delay as needed.
  console.debug('Map clicked with', evt);
}, 400);
// configure event listeners for map
google.maps.event.addListener(map, 'click', clickHandler);
google.maps.event.addListener(map, 'dblclick', clickHandler.cancel);

* Debounce.cancel est implémenté uniquement dans lodash (avec ce commit ), underscore.js ne l'implémente pas

3
Fabio

Une façon plus simple d'implémenter l'approche setTimeout() est de déclencher des événements personnalisés pour des clics simples.

La fonction suivante prend n'importe quel objet d'interface Google Maps (par exemple, carte, marqueur, polygone, etc.) et configure deux événements personnalisés:

singleclick: appelé 400 ms après un clic si aucun autre clic ne s'est produit

firstclick: appelé chaque fois qu'un événement de clic se produit, sauf si un clic s'est déjà produit au cours des 400 derniers ms (c'est pratique pour afficher une sorte de retour immédiat de clic à l'utilisateur)

function addSingleClickEvents(target) {
  var delay = 400;
  var clickTimer;
  var lastClickTime = 0;

  google.maps.event.addListener(target, 'click', handleClick);
  google.maps.event.addListener(target, 'dblclick', handleDoubleClick);

  function handleClick(e) {
    var clickTime = +new Date();

    var timeSinceLastClick = clickTime - lastClickTime;

    if(timeSinceLastClick > delay) {
      google.maps.event.trigger(target, 'firstclick', e);

      clickTimer = setTimeout(function() {
        google.maps.event.trigger(target, 'singleclick', e);
      }, delay);
    } else {
      clearTimeout(clickTimer);
    }

    lastClickTime = clickTime;
  }

  function handleDoubleClick(e) {
    clearTimeout(clickTimer);
    lastClickTime = +new Date();
  }
}

Vous pouvez l'utiliser comme ceci:

var map = ....
addSingleClickEvents(map);
google.maps.event.addListener(map, 'singleclick', function(event) {
    console.log("Single click detected at: " + event.latLng);
}
0
James