Обработка событий кликов в JS API Google Maps v3 при игнорировании двойных щелчков

С API Google Maps JS v3, я хочу удалить маркер, где пользователь нажимает на карту, сохраняя поведение по умолчанию, когда пользователь дважды щелкает (и не добавляет маркер на карту).

Я подумал об определении тайм-аута события click. Если в течение нескольких миллисекунд срабатывает событие двойного щелчка, тайм-аут отменяется. Если нет, маркер помещается на карту, когда истекает время ожидания. Но на самом деле это не похоже на лучшее решение.

Есть ли более элегантный способ справиться с этим?

Спасибо.

Ответ 1

Самый простой способ его решить.

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 лучше (см. ниже)

Ответ 2

Я только нашел хакерское решение, которое работает, но введет небольшое время ожидания (200 мс, это минимум, чтобы заставить его работать, но я не знаю, зависит ли он от клиента)

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);
});

Надеюсь, это поможет!

Ответ 3

Вы можете воспользоваться преимуществами dblclick fire, если это двойной щелчок, и один клик в таких случаях срабатывает только один раз.

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();
});

См. http://www.ilikeplaces.com

Ответ 4

Если вы используете underscore.js или * lodash здесь быстрый и элегантный способ решить эту проблему.

// 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 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 реализуется только в lodash (this commit), underscore.js не реализует его

Ответ 5

Более чистый способ реализации подхода setTimeout() - инициировать пользовательские события для одиночных кликов.

Следующая функция принимает любой объект интерфейса Google Maps (например, карту, маркер, многоугольник и т.д.) и устанавливает два пользовательских события:

singleclick: называется 400 мс после щелчка, если не произошло никаких других щелчков

firstclick: вызывается всякий раз, когда происходит событие клика, если только клик уже не произошел за последние 400 мс (это удобно для отображения какой-либо обратной связи с кликом для пользователя)

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();
  }
}

Вы можете использовать его так:

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

Ответ 6

Я не уверен, но если вы добавите обработчики событий для событий 'click' и 'dblclick', где вы говорите, что нужно нанести маркер на клик и не предпринимать никаких действий при двойном щелчке, вы можете пропустите добавление тайм-аутов (API-интерфейс карт может отличаться от того, что клик и что двойной щелчок)

google.maps.event.addListener(map, 'click', function (event) {
        placeMarker(event.latLng);
    });
google.maps.event.addListener(map, 'dblclick', function(event) { 
//DO NOTHING, BECAUSE IT IS DOUBLE CLICK
});

PlaceMarker (latLng) - пользовательская добавленная функция, которая добавляет маркер в заданное местоположение:

var marker = new google.maps.Marker({
        position: location,
        draggable: true,
        map: map
    });
map.setCenter(location);