Клуб API Карт

Обработчик клика по кластеру.

Пост в архиве.

Здравствуйте! Необходимо при кластеризации повесить собственный обработчик клика по кластерам (чтобы открывался не стандартный балун, а совсем не оносящийся к карте оверлей). Насколько я понял из документации, у Clusterer нет события click, и нижеприведённый код повесил обработчик на каждую из меток, находящихся внутри Clusterer.

clusterer = new ymaps.Clusterer(
clusterer.options.set({
    gridSize: 80,
    synchAdd: true,
    disableClickZoom: true
}
clusterer.add(PlacemarksArray);
clusterer.events.add('click', function (e) {
     alert('Клик!');
}
map.geoObjects.add(clusterer); 

Можно ли как-то обработать нажание при такой автоматической кластеризации, или же придётся создавать массив типа Cluster, обсчитывать вручную близлежайшие метки, распихивать их по кластерам, а при масштабировании всё пересчитывать заново (чего очень не хочется)?

16 комментариев

Да, к сожалению, сейчас кластеризатор не транслирует события с кластеров - починим это в следующем релизе.

Пока что могу посоветовать такой "хак" :

1. Задать пустой макет балуна кластера

2. Запретить показывать тень балуна

3. При открытии балуна (который по сути пустое место), показывать свой оверлей.

Отслеживать открытие балуна на кластере можно через map.balloon (все балуны работают через map.balloon).

 

clusterer.options.set({

   clusterBalloonLayout: ym.templateLayoutFactory.createClass(""),

   clusterBalloonShadow: false

 });

map.balloon.events.add('open', function (event) {

    // ваши действия

});

Спасибо! Попробую. Только ещё одна проблема: можно ли таким способом (или каким-то ещё) узнать, какие метки содержатся в данном кластере?

 

А ещё возникла такая идея: а нельзя переопределить функцию createCluster для кластеризатора, чтобы при создании очередного кластера на него вешался обработчик? Правда я не очень представляю себе, как это осуществить, и как вообще переопределять эту функцию. Если идея здравая, не могли бы вы накидать примерный код?

Да, и правда, это будет лучше и правильнее.

clusterer.createCluster = function(center, geoObjects) {

    var cluster = ymaps.Clusterer.prototype.createCluster.call(this, center, geoObjects);

    cluster.events.add('click', function(e){

       // останавливаем событие, чтобы балун кластера не открылся

       e.stopImmediatePropagation();

       // а дальше делаем что хотим

       .....

      // возвращаем кластер

     return cluster;

    });

};

 

А узнать, какие метки находятся в кластере, можно через 

cluster.properties.get('geoObjects');

 

А узнать, какие метки находятся в кластере, можно через 

cluster.properties.get('geoObjects');


Я правильно понимаю что так тоже можно:

cluster.getGeoObjects();

?

 

Да, можно и так.

А узнать, какие метки находятся в кластере, можно через

cluster.properties.get('geoObjects');

А если внутри обработчика клика, то к чему обращаться? К this или к e?

 

 

1. Можно обращаться прямо через cluster. Сработает замыкание, и обращение будет к тому кластеру, на который навешивали слушателя.

2. Можно через событие получить ссылку на кластер - e.get('target')

3. Можно при навешивании события третьим парметром указать контекст. Если в качестве контекста указать cluster, то обращаться к нему внутри функции-обработчика можно будет через this.

Ух как! Спасибо огромное! Теперь я знаю кунг-фу!)

При попытке переопределить .createCluster, получаю "b is underfined". Подскажите пожалуйста решение.

Для этого нужно как минимум посмотреть на ваш код)

clusterer = new ymaps.Clusterer() ;

clusterer.createCluster = function(center, geoObjects)
        {
            var cluster = ymaps.Clusterer.prototype.createCluster.call(this, center, geoObjects) ;
            cluster.events.add('click', function(e)
            {
                console.log('Кликнут кластер') ;   
                return cluster;
            }) ;
       
        };

Если блок с переопределением взять в комментарий, то ошибки не возникает и кластеризация работает. Соответственно я упускаю что-то в переопределении метода.

clusterer = new ymaps.Clusterer() ;

clusterer.createCluster = function(center, geoObjects)
        {
            var cluster = ymaps.Clusterer.prototype.createCluster.call(this, center, geoObjects) ;
            cluster.events.add('click', function(e)
            {
                console.log('Кликнут кластер') ;    
                return cluster;
            }) ;
            return cluster;
        };

Большое спасибо.

Добрый день! А на данный момент времени есть функционал в API для отлавливания клика по кластерной метке?
Необходимо было получение данных меток которые входят не в общий кластер, а в отдельный кластерный маркер. Реализовал таким образом:


clusterer.add(myGeoObjects);
myMap.geoObjects.add(clusterer);
// получение данных при клике на метку
const refreshVisibleList = (e) => {
const activePlacemark = e.get('target');


if (activePlacemark.properties.get('geoObjects')) {
console.log('Я кластер');
console.log(activePlacemark.properties.get('geoObjects'));
} else {
console.log('Я метка');
console.log(activePlacemark.properties._data);
}
};
const onClusterEvent = (e) => {
refreshVisibleList(e);
};
// Обновляем список гео-объектов при клике на маркер
clusterer.events.add('click', onClusterEvent);