Клуб API Карт

Закрывается балун кластера при изменении зума

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

Здравствуйте. у меня вопрос к знатокам) А это нормально что при изменении зума балун закрывается?  http://svadbagolik.cybers.net.ua/index2.php  что нужно зделать чтобы все балун не закрывался?

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

При изменении зума кластера генерируются заново. И соответственно балун будет закрываться. Сделать так, чтобы балун совсем не закрывался, невозможно. Возможно только заново открывать балун на нужном кластере или метке.

я поцепил определение того какой балун был открыт на уже существующие событие 

 

     

  /*

 * Далее по коду скрываем балун, когда точка его привязки выходит за видимую область на карте.

 */       

    myMap.balloon.events

                // При открытии балуна начинаем слушать изменение центра карты

                    .add('open', function (e) {

                    

                        var balloon = e.get('balloon'),

                          isRemoved = false;     

                        

                        eventsGroup = myMap.action.events.group().add('tick', function (e) {

                            var mapCenter = e.get('tick').globalPixelCenter,

                                mapBounds = [

                                    [mapCenter[0] - mapSize[0] / 2, mapCenter[1] - mapSize[1] / 2],

                                    [mapCenter[0] + mapSize[0] / 2, mapCenter[1] + mapSize[1] / 2]

                                ],

                                isVisible = isPointInBounds(mapBounds, balloon.getPosition());

                            // Проверяем, находится ли балун в видимой области

                            if (!isVisible && !isRemoved) {

                                balloon.close();

                               // openForZoom=null;

                               

                                isRemoved = true;

                            } else if (isVisible && isRemoved) {

                                balloon.open();

                                isRemoved = false;

                            }

                        });

                        openForZoom=balloon.getData().properties.get('myid');//определил номер балуна

                    })

                // При закрытии балуна удаляем слушатели

                    .add('close', function () {

                        eventsGroup.removeAll();

                       // openForZoom=null;///вот тут одна из загвоздок

                        console.log('close');

                    });

 

а потом проверяю на таком событии существует ли параметр openForZoom

 

 

 cluster.events.add('objectsaddtomap', function () {

        

        if(openForZoom){

            console.log(openForZoom);

                        // Получим данные о состоянии объекта внутри кластера.

                var geoObjectState = cluster.getObjectState(myPlacemark[openForZoom]);

                // Проверяем, находится ли объект находится в видимой области карты.

               ///if объект попадает в кластер, открываем балун кластера с нужным выбранным объектом.

                    if (geoObjectState.isClustered) {

                        //geoObjectState.cluster.state.set('activeObject', myPlacemark[openForZoom]);

                        geoObjectState.cluster.balloon.open();

                        console.log('pervoe');

                    } else {

                        // Если объект не попал в кластер, открываем его собственный балун.

                        myPlacemark[openForZoom].balloon.open();

                        console.log('vtoroe');

                    }

                

        }

})

 

 

проблемы:

1) притаком раскладе, я не знаю где прописать убиение openForZoom ну что б например при закрытии пользователем балуна, при следующей перестройке кластера балун снова не открылся. хотел повесить это на 

 

 

 .add('close', function () {

                        eventsGroup.removeAll();

                       // openForZoom=null;///вот тут одна из загвоздок

                        console.log('close');

                    });

 

но если я уберу комментарий то при перестройке балуна эта переменная умрет и не откроет балуна.

2. при измении зума (перестройке кластера), осуществляется проверка того балун одиночный или нет, и соответственно открывается нужный балун, но если одиночный срабатывает нормально то балун где несколько меток там в именно необходимую метку не подгрузаются данные и она пустая остается.

3. ох и костылей наставлено(

страничка   http://svadbagolik.cybers.net.ua/index2.php

 

 

Сайт же пока в разработке, да? Пришлете ссылку, когда запуститесь?

да, пока еще мучаюсь. Потом ссылочку скину =)

 

а зачем открывать баллун именно кластера? может, проще повесить "click" на слкастеры и передавать данные "просто" баллуну?

типа так: 

map.geoObjects.events.add('click', function(e) {

map.balloon.open(e.get('target').geometry.getCoordinates(), {

// тут передадим данные

}

})

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

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

кстати, на днях решили как правильно зумить карту с открытым баллуном.

вот оно:

map.setZoom = function (zoom, options) {

    var globalPixelCenter = this.getGlobalPixelCenter(),
        scale = Math.pow(2, zoom - this.getZoom()),
        newPixelCenter = [globalPixelCenter[0] * scale, globalPixelCenter[1] * scale];

    if (/*это кстати кто?*/self.balloon && self.balloon.isOpen()) {
        var ballonCenter = map.options.get('projection').toGlobalPixels(self.balloon.getPosition(), this.getZoom()),
            offsetBase = [(ballonCenter[0] - globalPixelCenter[0]), (ballonCenter[1] - globalPixelCenter[1])];
        newPixelCenter[0] += offsetBase[0] * scale - offsetBase[0];

        newPixelCenter[1] += offsetBase[1] * scale - offsetBase[1];

    }

    this.setGlobalPixelCenter(newPixelCenter, zoom, options);
}

ага, класная фишка, а про нее вчера читал.

вставил к себе этот код, оно не работает, чувствую я не все передаю особенно в этой строке

map.setZoom = function (zoom, options) {

подскажите что я должен указать в options и zoom

ничего.

этот код переопределяет встроенную в апи функцию setZoom.

я просто чего спрашиваю, у меня при таком раскладе балун не ведет себя так как у Вас, или это все из-за того что у нас разные балуны?

в функцию надо передавать координаты открытого баллуна.

в получить их можно только одним способом - запомнить.

то есть при открытии баллуна надо ссылку на него сохранять:

var balloon = блаблабла.open();

с вот эту ссылку (balloon) надо отдавать в функцию. 

в смысле не отдавать, а держать доступной.

дайте ваш код - поглядим

вот мой код при открытии балуна

myMap.balloon.events
                // При открытии балуна начинаем слушать изменение центра карты
                    .add('open', function (e) {
                        var balloon = e.get('balloon'),
                        isRemoved = false;
                        eventsGroup = myMap.action.events.group().add('tick', function (e) {
                           
                            var mapCenter = e.get('tick').globalPixelCenter,
                                mapBounds = [
                                    [mapCenter[0] - mapSize[0] / 2, mapCenter[1] - mapSize[1] / 2],
                                    [mapCenter[0] + mapSize[0] / 2, mapCenter[1] + mapSize[1] / 2]
                                ],
                                isVisible = isPointInBounds(mapBounds, balloon.getPosition());
                                mov=1;
                            // Проверяем, находится ли балун в видимой области
                            if (!isVisible && !isRemoved) {
                                balloon.close();
                               // openForZoom=null;
                                isRemoved = true;
                                mov=null;
                            } else if (isVisible && isRemoved) {
                                balloon.open();
                                isRemoved = false;
                            }
                        });
                       
                        if(balloon.getData().properties.get('myid')){
                        openForZoom=balloon.getData().properties.get('myid');//вот тут я запоминаю ИД открытого балуна
                        openCoord=balloon.getPosition();//запомнил координаты
                        }
                    })

вот код после чего я начинаю проверять если до перестройки балуна был открыт балун, то я его снова открываю, проверевши находиться он в кластере или сам

 

// Поскольку по умолчанию объекты добавляются асинхронно,
// обработку данных можно делать только после события, сигнализирующего об
// окончании добавления объектов на карту.
    cluster.events.add('objectsaddtomap', function () {
        if(openForZoom){
                        // Получим данные о состоянии объекта внутри кластера.
                var geoObjectState = cluster.getObjectState(myPlacemark[openForZoom]);
                // Проверяем, находится ли объект находится в видимой области карты.
               ///и объект попадает в кластер, открываем балун кластера с нужным выбранным объектом.
                if (geoObjectState.isShown) {
                    if (geoObjectState.isClustered) {
                        geoObjectState.cluster.state.set('activeObject', myPlacemark[openForZoom]);
                        geoObjectState.cluster.balloon.open();
                    } else {
                        // Если объект не попал в кластер, открываем его собственный балун.
                        myPlacemark[openForZoom].balloon.open();
                    }
                }
        }

})

ну а функция зума у меня не отличается от вашей, главна проблема которая меня смущает это то что при зуме (-) балун всегда на видимой части карты, а когда уходим в (+) она понемного сдвигается в сторону, что есть не красиво)

myMap.balloon.events
                // При открытии балуна начинаем слушать изменение центра карты
                    .add('open', function (e) {
                        var balloon = e.get('balloon'),
                        isRemoved = false;
                        eventsGroup = myMap.action.events.group().add('tick', function (e) {
                            
                            var mapCenter = e.get('tick').globalPixelCenter,
                                mapBounds = [
                                    [mapCenter[0] - mapSize[0] / 2, mapCenter[1] - mapSize[1] / 2],
                                    [mapCenter[0] + mapSize[0] / 2, mapCenter[1] + mapSize[1] / 2]
                                ],
                                isVisible = isPointInBounds(mapBounds, balloon.getPosition());
                                mov=1;
                            // Проверяем, находится ли балун в видимой области
                            if (!isVisible && !isRemoved) {
                                balloon.close();
                               // openForZoom=null;
                                isRemoved = true;
                                mov=null;
                            } else if (isVisible && isRemoved) {
                                balloon.open();
                                isRemoved = false;
                            }
                        });
                        
                        if(balloon.getData().properties.get('myid')){
                        openForZoom=balloon.getData().properties.get('myid');//вот тут я запоминаю ИД открытого балуна
                        openCoord=balloon.getPosition();//запомнил координаты
                        }
                    })


следить за тиками не нужно. тики самы вызывают map.setZoom, а там у Вас подмененная функция. это раз.

второе - надо вынести balloon в область видимости setZoom/

var balloon;

map.setZoom = function( ...

myMap.balloon.events
                // При открытии балуна начинаем слушать изменение центра карты
                    .add('open', function (e) {
                        var balloon = e.get('balloon'),
                        isRemoved = false;

Здравствуйте. только что попробовал
myMap.balloon.events
                // При открытии балуна начинаем слушать изменение центра карты
                    .add('open', function (e) {
                        balloon = e.get('balloon'),
                        isRemoved = false;
тайлы карты не видны, что-то не так. а насчет tick, то он там для другого, для отслеживание вышел балун за пределы карты или нет. Так как balloonPane: 'movableOuters' немного не доработан в этом релизе. но сейчас не о нем)

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

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

 // geoObjectState.cluster.state.set('activeObject', myPlacemark[openForZoom]);

3. Вы хотите много необычного, что поделать(

1. это нужно в двух шаблонах балуна эту кнопку добавить в обычного балуна и кластерного?

2. раскоментировал, он стал активным, но не подгрузилась все-равно информация

 

Да, по идее макет и там и там должен быть одинаковый.

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

спасибо, сейчас попробую разобраться.

 

получилось, там был небольшой логический затуп)

 

Это прекрасно =)

Марина, я знаю Вы умеете предсказывать выход нового релиза) Когда он выйдет на свет?

Еще навожу порчу по CSS  и снимаю сглаз на баги) новый релиз ожидается к началу октября

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

 

Выдадим вам значок "главный сапер" :-)