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

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

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

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

Спасибо.


person Pierre    schedule 16.03.2011    source источник


Ответы (6)


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

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

person rebeliagamer    schedule 15.07.2011
comment
Это решение не работает, если ваша функция placeMarker() может вызываться иногда помимо событий щелчка (если только вы не всегда вызываете mapZoom = map.getZoom() перед вызовом placeMarker()); Я нашел решение @ShogunPanda более гибким в этом случае. - person Quinn Comendant; 17.06.2015

Я только что нашел хакерское решение, которое работает, но вводит небольшое время ожидания (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);
});

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

person ShogunPanda    schedule 07.12.2011
comment
Я пробовал это, но не работает для меня. первый щелчок в двойном щелчке очищает тайм-аут, но второй щелчок по-прежнему действует как щелчок, и выполняется do_something_here(). - person Luis A. Florit; 29.10.2015
comment
Тем не менее, установка глобальной переменной doubleClicked = true в функции dblclick и проверка ее внутри update_timeout решили проблему. ;) - person Luis A. Florit; 29.10.2015

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

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.

person Ravindranath Akila    schedule 28.04.2011
comment
Работает отлично! Если вам, как и мне, нужно было отправить событие в функцию runIfNotDblClick, вы можете сделать: setTimeout(runIfNotDblClick.bind(null, event), 500) и, например, прочитать latLng в событии, используя Array.prototype.slice.call(arguments)[0].latLng - person riper; 08.01.2018

Если вы используете 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'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 реализован только в lodash (с этим коммитом), underscore.js не реализует это

person Fabio    schedule 16.11.2015

Более чистый способ реализации подхода 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);
}
person James    schedule 08.05.2015

Я не уверен, но если вы добавите обработчики событий к событиям «щелчок» и «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);
person GoG    schedule 16.03.2011
comment
Спасибо за Ваш ответ. Но API запускает как щелчок, так и событие dblclick, когда пользователь дважды щелкает:/ - person Pierre; 17.03.2011