Клуб API Карт

показ балуна после загрузки метки

i.am.ph
26 ноября 2010, 15:20

Всем привет.

Ситуация следующая: использую ObjectManager для работы с большим количество меток.

Задача состоит в том, чтобы по клику по ссылке делать центром карты нужную метку и открывать у этой метки балун.

Ссылку на метку запоминаю, когда создаю ее.

Алгоритм такой: нахожу ссылку на метку, далее смотрю min_zoom и max_zoom у этой метки и смотрю текущий зум у карты. Соответственно, меняю его, если он не попадает в диапазон [min_zoom;max_zoom] точки.

Далее делаю setCenter и передаю координаты метки.

Далее вызываю openBallon() у метки.

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

Опытным путем удалось выяснить, что проблема в том, что центр (или масштаб) карты меняется, тогда начинается перерисовка карты. И похоже балун не открывается до того момента, пока нужная метка не будет полностью отрисована.

Собственно, вопрос вот в чем: есть ли какой-нибудь эвент отрисовки точки или как решить эту проблему?

Перепробовал уже кучу способов, пробовал использовать Update эвент у карты, но это немного не то.

Всем спасибо за внимание.

15 комментариев
Подписаться на комментарии к посту

Далее делаю setCenter и передаю координаты метки.


Далее вызываю openBallon() у метки, обернутый в setTimeout на полсекунды


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

Хм,а кто гарантирует, что у юзера за эти полсекунды успеет загрузиться карта? Если он с телефона сидит на EDGE?
полсекунда - гарантия на центрирование и зум карты.
после чего открывается балун. с гарантией
после чего под ним появляются тайлы.

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

вобщем не вариант, хочется нормального решения этого вопроса.
в опыты закралась ошибка.
загрузка тайлов, дейсвия карты, анимация банеров - это паралельные операции которые при всем желании друг на друга не завязаны.
Получается тогда на каком же моменте появляется задержка и почему не появляется балун, не могли бы вы пояснить?
Почему процесс центровки не может проходить более чем полсекунды? Теоретически-то это возможно, если допустим компьютер слабый очень.
и теоритически и практически не возможно :), да ну ладно - глюки бывают феерические на любой системе.


перед отправкой команды на центрирование - подвестись на moveend карты. 
таким образом ровно по окончанию движения будет вызван ваш обработчик. 
только не забудьте его потом снять
moveend почему-то не срабатывает, когда вызываю setCenter и setZoom. Срабатывает, когда допустим я сам перемещаюсь по карте.

Зато срабатывает событие Update. Однако оно срабатывает, вылетает алерт (указанные в обработчике события), жму "ОК" и только потом появляются метки в данном зуме и в данной области.
то есть балун в обработчике этого события тоже не сработает..
Как-то необходимо вызывать балун уже после того, как отрисовались актуальные на данный момент точки..

Да, вариант с setTimeout вроде работает.. Но что-то не нравится мне это решение совсем..
запустите открытие в таймауте на 100 мсек( возможно хватит и 1 мсек).
запустите это по событию Update :)
Вы можете воспользоваться методами карты panTo и setZoom. У них можно задать callback-функцию, которая вызовется после окончания работы метода.
Вот так примерно:



var placemark = new YMaps.Placemark(new YMaps.GeoPoint(37, 55));
placemark.metaDataProperty = {
    zoom : 16   // Масштаб, на который нужно зазумиться на данной точке
};
map.addOverlay(placemark);

// Летим к точке
map.panTo(placemark.getGeoPoint(), {

    // Потом зумимся
    callback : function () {
        map.setZoom(placemark.metaDataProperty.zoom, {

            // Плавно зумимся, кстати
            smooth : true,

            // А после окончания всех операций открываем балун                                                                                                
            callback : function () {
                placemark.openBalloon();
            }
        });
    }
});



А можно еще хитрее поступить и заюзать метод zoomBy:




map.zoomBy(placemark.metaDataProperty.zoom - map.getZoom(), {
    position : placemark.getGeoPoint(),
    centering : true,
    callback : function () {
        placemark.openBalloon()
    }
});



В обоих случаях балун открывается только после второго клика.
Но спасибо за предложения ;)
У меня открывается с первого раза.

Тестировал с помощью такого кода:

YMaps.jQuery(function () {
    var map = new YMaps.Map(YMaps.jQuery("#YMapsID"));
    map.setCenter(new YMaps.GeoPoint(37.64, 55.76), 10);
    map.addControl(new YMaps.Zoom());

    var placemark = new YMaps.Placemark(new YMaps.GeoPoint(37, 55));
    placemark.metaDataProperty = { zoom : 16 };
    map.addOverlay(placemark);

    YMaps.jQuery("#openBalloon").bind("click", function () {
        map.zoomBy(placemark.metaDataProperty.zoom - map.getZoom(), {
            position : placemark.getGeoPoint(),
            centering : true,
            callback : function () {
                placemark.openBalloon()
            }
        });
    });
});

Соответственно html вот такой:


open

Не могли бы вы дать ссылку на свою страничку с проблемой?
Суть проблемы в том, что для удаленной с карты метки, нельзя открыть балун. А менеджер объектов именно удаляет метки с карты, когда они находятся вне зоны видимости (и добавляет, когда они попадают в эту зону). Более того, менеджер объектов добавляет/удаляет метки асинхронно. Именно поэтому после setCenter не срабатывает openBallon у метки - метка еще не добавлена на карту.

Вариант решения:
События, сигнализирующего о добавлении метки на карту нет.
Поэтому как решение примерно такой код:

                myMap = new YMaps.Map(YMaps.jQuery("#YMapsID"));
                myMap.setCenter(new YMaps.GeoPoint(37.64, 55.76), 9);

                var placemark = new YMaps.Placemark(new YMaps.GeoPoint(1, 1)),
                      om = new YMaps.ObjectManager();
                om.add(placemark);
                myMap.addOverlay(om);

                myMap.setCenter(new YMaps.GeoPoint(1, 1));
                var intervaId = setInterval(function () {
                    if (placemark.getMap()) {
                        clearInterval(intervaId);
                        placemark.openBalloon();
                    }
                }, 100);


Спасибо за разъяснение! :)