Клуб API Карт

Зум при открытом баллуне

Пост в архиве.
nolan23
4 сентября 2012, 10:31

Я все продолжнаю переделывать карты с гугла на яндекс.

Столкнулся с такой задачей:

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

как бы побороть сей недуг?)

 

попробовал так:
add('actiontick', function(e) {
                var tick = e.get('tick');
                if (self.balloon && self.balloon.isOpen() && tick.zoom != map.getZoom()) {
                    var coords = self.balloon.getPosition(),
                        globalPixel = map.options.get('projection').toGlobalPixels(coords, map.getZoom()),
                        mapCenter = map.getGlobalPixelCenter(),
                        // коэфициент масштабирования в глобальных кординатах
                        k = Math.pow(2, tick.zoom) / Math.pow(2, map.getZoom()),
                        // смещение баллуна на зуме карты
                        offsetBase = [(globalPixel[0] - mapCenter[0]), (globalPixel[1] - mapCenter[1])],
                        // смещение баллуна на зуме тика
                        offset = [offsetBase[0] * k, offsetBase[1] * k],
                        // глобальные пиксельные координаты баллуна на тике
                        tickPixel = map.options.get('projection').toGlobalPixels(coords, tick.zoom);
                    // глобальные пиксельные координаты центра на тике
                    tick.globalPixelCenter = [tickPixel[0] - offset[0], tickPixel[1] - offset[1]];
                }
            }).

но, похоже, управлять тиком из события не получится.
кстати, вот тут очень бы пригодилась возможность получения координат у открытого баллуна. иначе приходится костылять тем, что сохранять каждый раз переменную баллуна в свойствах контроллера.
другой вариант - написать самостоятельно кастомный контрол зума (что не хочется совсем) или перехватывать события дефолтного контрола.
как быть?
посмотреть можно тут http://www.pomnivoinu.ru/map/index.php открываем баллун любой метки и зумим контролом.

 

 

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

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

Только лучше перегрузи map.setZoom на корню.

 

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;
        newPixelCenter[1] += offsetBase[1] * scale;
    }

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

 

 

о! спасипки!

self.balloon - это свойство контроллера, которое приходится переопределять вот так:

self.balloon = placemark.balloon.open();

потому что получить позицию баллуна не получается.

map.balloon - не содержит свойств (ну, или я друак)))

поле properties не содержит, но кажется данные можно получить через getData()

нет такого метода(((

 

var b = map.balloon.open(map.getCenter(), { content : 'text' });

console.log(b.getData().content);

setTimeout(function () {
    b.setData({content: 'new text'});
}, 2000);

 

ненене.

вот так:

map.balloon.open(map.getCenter(), { content : 'text' });

console.log(map.balloon.getData());  //error

setTimeout(function () {
    map.balloon.setData({content: 'new text'});  //error
}, 2000);


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

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

мы тебя поняли

будем думать про один балун

кстати, твой скрипт чутка не так отрабатывает.

в гугле баллун намертво прибивается к положению на странице. 

а в твоем варианте почему-то при зуме баллун центрируется.

шас поковыряюсь еще.

во!

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

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

теперь красиво!

http://www.pomnivoinu.ru/map/index1.php

udp!!

полная петрушка((

self.balloon.getPosition() иногда возвращает ПИКСЕЛЬНЫЕ координаты, иногда - географические. отчего зависит - не знаю.

поставил костыль:

var balloonGeo = self.balloon.getPosition(),balloonPixel = (balloonGeo[0] > 180 || balloonGeo[1] > 180) ? balloonGeo : map.options.get('projection').toGlobalPixels(balloonGeo, this.getZoom()),воспроизведение:http://www.pomnivoinu.ru/map/index1.php
регистрируемся и ставим маркер через добавление.ставим брейпоинт на map1.js:376зумим контролом.