Клуб API Карт

Программируемая метка кластера

Пост в архиве.
dearfriend.web
22 ноября 2013, 10:14

Добрый день!

столкнулся с такой задачей - вывод на карту объектов, у многих из которых одинаковые координаты - использую кластеры. Метку задаю через options.icons. Подскажите, как можно задавать метки кластерам в зависимости от их содержания?

мой код сейчас:

 


        window.clusterer = byColor.clusterize(
            {
                clusterDisableClickZoom:true,
                groupByCoordinates:true,
                clusterBalloonLayout:clusterClass,
                clusterBalloonShadow: false,
                icons: getIcons()
            }
        );

    function getIcons(){
       
        var clusterIcons = [{
            href: '/images/pricemap/12.png',
            size: [20, 20],
            offset: [-10, -10]
        }];
        return clusterIcons;
    }

 

И еще один вопрос, связанный с кластерами - как можно удалить с карты все кластеры? Точки удаляю циклом


            myMap.geoObjects.each(function(geoObject){
                myMap.geoObjects.remove(geoObject);
            });

 
Кластеры остаются :(

 

Спасибо!

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

По поводу п.1

Надо переопределить метод createCluster

clusterer.createCluster = function (center, geoObjects) {

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

   //  При создании кластера передаете в функцию getIcons геообъекты и

  // в зависимости от содержимого выставляете нужные метки.

   cluster.options.set('icons', getIcons(geoObjects));

   return cluster;

    }

}

 

По поводу п.2 надо разбираться в коде. У вас есть код целиком, а лучше ссылка на страницу?


    ymaps.ready(init);
       
    function init() {
        var myMap = new ymaps.Map('pricemap', {
                center: [53.35, 83.7],
                zoom: 13
            });
           
        myMap.controls.add(
           new ymaps.control.SmallZoomControl()
        );
        var myObjects = new ymaps.geoQuery();
        var myCollection = new ymaps.GeoObjectCollection();
       
        var bounds = myMap.getBounds();
       
        var left = bounds[0][0];
        var right = bounds[1][0];
        var top = bounds[0][1];
        var bottom = bounds[1][1];
       
        myMap.events.add('boundschange', function (e) {
            myMap.geoObjects.each(function(geoObject){
                myMap.geoObjects.remove(geoObject);             //удалились только метки
            });
            var bounds = myMap.getBounds();
            var left = bounds[0][0];
            var right = bounds[1][0];
            var top = bounds[0][1];
            var bottom = bounds[1][1];
            updateMap(myMap,myCollection,left,right,top,bottom);
        });
        $('#map-search').click(function(){
           
            updateMap(myMap,myCollection,left,right,top,bottom);
        });
    }
   
    function updateMap(myMap,myCollection,left,right,top,bottom){

               //формируем аякс-запрос к серверу


                success: function(response) {
                    if (response.code == 'success'){
                       
                        var geo = {
                            type: "FeatureCollection",
                            features: []
                        };
                        for (var i = 0; i < response.coords.length; i++) {
                           
                            geo.features.push({
                                type: 'Feature',
                                geometry: {
                                    type: 'Point',
                                    coordinates: [response.coords[i].xx, response.coords[i].yy],
                                    radius: 10000
                                },
                                options: {
                                    iconImageHref:'/images/'+response.coords[i].group+'.png',      //выставляем для каждой метки свою точку
                                    iconImageSize: [12, 12],
                                    iconImageOffset: [-6, -6],
                                    name:'grade_'+response.coords[i].group,
                                },
                                properties: {
                                    balloonContentHeader: response.coords[i].street,
                                    number:response.coords[i].n
                                }
                            });
                        }
                        window.myObjects = new ymaps.geoQuery(geo);
                       
                        $('.map-filter-legend').html(response.grade);
                       
                        $('.map-filter-legend input').change(function(){
                            checkState(myMap);                   .//поиск по параметрам (отобразить/скрыть)
                        });
                        checkState(myMap);
                    }
                }
            });
        }
    }
   
    function checkState (myMap) {
        var shownObjects,
            byColor = new ymaps.GeoQueryResult();
       
        // Отберем объекты по цвету.
        if ($('#grade_1').prop('checked')) {byColor = myObjects.search('options.name = "grade_1"').add(byColor);}
        if ($('#grade_2').prop('checked')) {byColor = myObjects.search('options.name = "grade_2"').add(byColor);}
        if ($('#grade_3').prop('checked')) {byColor = myObjects.search('options.name = "grade_3"').add(byColor);}
        if ($('#grade_4').prop('checked')) {byColor = myObjects.search('options.name = "grade_4"').add(byColor);}
        if ($('#grade_5').prop('checked')) {byColor = myObjects.search('options.name = "grade_5"').add(byColor);}
        if ($('#grade_6').prop('checked')) {byColor = myObjects.search('options.name = "grade_6"').add(byColor);}
        if ($('#grade_7').prop('checked')) {byColor = myObjects.search('options.name = "grade_7"').add(byColor);}
        if ($('#grade_8').prop('checked')) {byColor = myObjects.search('options.name = "grade_8"').add(byColor);}
        if ($('#grade_9').prop('checked')) {byColor = myObjects.search('options.name = "grade_9"').add(byColor);}
        if ($('#grade_10').prop('checked')) {byColor = myObjects.search('options.name = "grade_10"').add(byColor);}
        if ($('#grade_11').prop('checked')) {byColor = myObjects.search('options.name = "grade_11"').add(byColor);}
        if ($('#grade_12').prop('checked')) {byColor = myObjects.search('options.name = "grade_11"').add(byColor);}
       
        shownObjects = byColor;
        byColor.each(function(point){
            point.events.add(['click'],
                function (e) {
                    //подписали каждую метку на аякс запрос
                }
            );
        });
       
       
        var clusterClass =  ymaps.templateLayoutFactory.createClass(
            '',{
                build:function(){
                    this.constructor.superclass.build.call(this);
                    var geoObjects = this.getData().properties.get('geoObjects');
                    var nums = [];
                    for(var i=0;i< geoObjects.length;i++){
                        nums.push(geoObjects[i].properties.get('number'));
                    }
                    $('.map-filter-legend').load('/pricemap/get_flats',{id:nums},function(){
                        $('.map-filter-legend a').click(function(){
                            var id = $(this).attr('id');
                            id = id.split('_')[1];
                            //снова аякс
                        });
                    });
                }
            }
        );
       
        window.clusterer = byColor.clusterize(
            {
                clusterDisableClickZoom:true,
                groupByCoordinates:true,
                clusterBalloonLayout:clusterClass,
                clusterBalloonShadow: false,
                icons: getIcons()
            }
        );
        myMap.geoObjects.add(clusterer);
        // Объекты, которые не попали в выборку, нужно убрать с карты.
        myObjects.remove(shownObjects).removeFromMap(myMap);

    }
    function getIcons(){
       
        var clusterIcons = [{
            href: '/images/pricemap/12.png',
            size: [20, 20],
            offset: [-10, -10]
        }];
        return clusterIcons;
    }

 

Спасибо!

Ну тут конечно тяжело разобраться без ссылки. У меня есть предположение, что действия выполняются просто не в том порядке. Например сначала происходит событие  boundschange и удаление объектов с карты, а потом приходит ответ ajax-запроса и кластеризатор добавляется на карту.

прошу прощения, ввел в заблуждение:) кластеры удаляются, все отлично.

Проблема другая - в перестройке кластеров, когда я скрываю некоторые элементы способом, описанным тут - http://api.yandex.ru/maps/jsbox/geoobjects_menu

На одних точках все работало как часы, с использованием кластеризации все сломалось - не скрываются ни точки, ни кластеры :(.

Кстати, если объекты изначально скрыты, то добавляется все корректно.

 

Спасибо за помощь

Вы наверное используете строчку ровно как в примере.

myObjects.remove(shownObjects).removeFromMap(myMap);

 

Этот код удаляет объекты только с карты. А если объекты находятся в кластеризаторе, то они уже прикреплены не к карте, а к кластеризатору.

Чтобы удалить выборку из кластеризатора, нужно выполнить такой код.

geoQueryResult.removeFrom(clusterer);

 

Если объекты разбросаны по карте и кластеризаторам и надо удалить все, можно написать так.

geoQueryResult.removeFrom(clusterer).removeFrom(map.geoObjects);

Действительно, это работает, спасибо!

Ну и напоследок вопросик: сейчас,если класте содержит 3 и более меток, события скрытия и показа работают отлично. Но если в кластере 2 метки и мы убираем одну, то сам кластер с карты не исчезает, и поверх него появляется метка, якобы не кластеризованная - ну одна ж, незачем вроде. Что можно посмотреть на этот счет?

Спасибо еще раз :)

Это очень похоже на баг, починим в будущих релизах. Сейчас у кластеризатора есть метод refresh, можно попробовать его вызывать после добавления-удаления меток. Правда рефреш занимает некоторое время(

Всеволод Шмыров
25 ноября 2013, 13:50
Доброе утро!
Могли вы сказать какую версию API используете? 2.0?
Могли бы показать код именно этой ситуации ? Вы добавляете три геообъекта в кластеризатор и удаляете только два ? или вы у них меняете опцию visible ?

Доброе! апи 2.0.

Добавляю 3 объекта, удаляю 2 из них (removeFrom(clusterer)).

       myObjects - json описание меток

 

        window.clusterer = byColor.clusterize(

            {

                clusterDisableClickZoom:true,

                groupByCoordinates:true,

                clusterBalloonLayout:clusterClass,

                clusterBalloonShadow: false,

            }

        );

        myMap.geoObjects.add(clusterer);

 

        myObjects.remove(byColor).removeFromMap(myMap).removeFrom(clusterer);

 

Решил проблему с помощью этого примера