Клуб API Карт

balloonAutoPan или сдвиг балуна на видимую часть карты, разбираемся (Решено!) ^___^

Пост в архиве.
belyanskii
29 августа 2012, 14:47

Доброго времени суток товарищи! :)

Пытаюсь найти решение следующей проблемы...у меня имеются метки на карте и кастомный балун для них.

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

 

Цель - при нажатии на балун центрировать карту по координатам метки + сделать "сдвиг" на определенное кол.-во пикселей О__О или же заставить работать balloonAutoPan.

 

Приглашаю знатоков для дискуссии =)

 

UPD - ссылку дать не могу, NDA....могу подробнее объяснить работу и показать части кода :)

И так, использую я yaml фаил с данными по объектам., все объекты добавляются в кластер и располагаются на карте.

Код для этих вещей весьма тривиальный и не самый красивый я полагаю:

 

 

// загружаем объекты 

ymaps.geoXml.load('/yaml.xml').then(function (res) {
var arr = [];
res.geoObjects.each(function (obj) {
arr.push(obj);
});

cluster.add(arr);

myMap.geoObjects.add(cluster);
});

 

// шаблон контента для балуна


var ObjectBaloonContent = ymaps.templateLayoutFactory.createClass('', {
build: function (){

var parent = this.getParentElement();

var geoObject = this.getData().properties;

var content = '';

parent.innerHTML = content;
}

});

 

 

 

UPD 2 - проблема №2 - "назначение событий на отдельный placemark api Яндекс.карт 2.0", нашел в поиске тему по её решению но пример кода который там приведен не сработал....Необходимо добавить событие клик для всех меток на карте, для получения координат и центрирования карты со сдвигом :)

 

Задача решена!

 

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

 

    var geoObject = e.get('target');

 

    var projection = myMap.options.get('projection');

 

    var position = geoObject.geometry.getCoordinates();

 

    var position_global_px = myMap.converter.pageToGlobal(projection.fromGlobalPixels(position, myMap.getZoom()));

 

    var position_local_px = myMap.converter.globalToPage(projection.toGlobalPixels(position,myMap.getZoom()));

 

 

    myMap.setGlobalPixelCenter([position_global_px[0] + position_local_px[0], position_global_px[1] + position_local_px[1]]);

 

 

}, this);

 

Как это работает я полностью и не знаю :)

Если есть что дополнить/поправить - wellcome!

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

Если честно, я толком не поняла проблему. У нас часто спрашивают, как открыть балун метки в кластеризаторе, если она в это время находится за пределами видимой области карты. Может вам тоже нужно это сделать?

нет, мне нужно подвинуть карту так, чтобы балун был виден полностью :)

балун не стандартен и обычным balloonAutoPan проблему не решить :(

 

Ну тогда так.

1. берете центр метки

2. Вычисляете локальные пиксельные координаты этого центра через map.converter - это будет позиция метки относительно прямоугольной области отображения карты

3. Смотрите, насколько нужно сдвинуть центр карты, чтобы балун влез

4. Сдвинуть карту на это число пикселей  - получить центр карты getGlobalPixelCenter, прибавить отступы и перезадать центр через setGlobalPixelCenter

попробуемс! :)

Стал вопрос с точками на карте, иконка для них у меня определена в yaml файле....и все, больше никаких опций нет.

А мне, как я понимаю, надо задать для всех точек на карте, чтобы при клике на точку выполнять функцию определения координат и т.д. Сейчас попытаюсь найти решение, если есть идеи - wellcome =)

Все клики на метках пропагируются вверх. То есть клики можно слушать на родительских коллекциях.

Можно слушать клики на всех геообъектах карты

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

    var geoObject = e.get('target');

    // выполняем действия...

}, this);

 

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

Добавил следующий код в функцию инициализации:

myMap.geoObjects.add('click', function (e) {

 

    var geoObject = e.get('target');

 

    console.log('aaa');

 

}, this);

 

не происходит ничего т_т

Извините, пропустила events.

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

 

    var geoObject = e.get('target');

 

    console.log('aaa');

 

}, this);

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

    var geoObject = e.get('target');

    

    var projection = myMap.options.get('projection');

    var position = geoObject.geometry.getCoordinates();

    var positionpx = myMap.converter.globalToPage(projection.toGlobalPixels(position, myMap.getZoom()));

 

    myMap.setGlobalPixelCenter([ positionpx[0] , positionpx[1] ]);

 

}, this);

 

Сделал так, но меня уносит куда-то в океан) по моему перемудрил с конвертацией Т___Т

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

    var geoObject = e.get('target');

    

    var projection = myMap.options.get('projection');

    var position = geoObject.geometry.getCoordinates();

    var positionpx = myMap.converter.globalToPage(projection.toGlobalPixels(position, myMap.getZoom()));

    // теперь у вас в переменной positionpx хранятся локальные пиксели

   // с их помощью нужно рассчитать, на сколько нужно сместить центр карты, чтобы был виден балун целиком

   // допустим выяснилось, что центр карты надо сместить на 10 пикселей в обе стороны

    var oldGlobalPixelCenter = myMap.getGlobalPixelCenter();

    myMap.setGlobalPixelCenter([oldGlobalPixelCenter[0] + 10, oldGlobalPixelCenter[1] + 10]);

 

}, this);

 

А уж расчет смещения центра карты - это целиком ваша задача, все зависит от логики построения балуна.

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

myMap.setGlobalPixelCenter([ positionpx[0] , positionpx[1] ]);


но меня перебрасывало куда-то в океан :)

Вы поняли, почему вас перебрасывало? Нужна еще помощь?

Еще немного! :)

Я переделал -

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

    var geoObject = e.get('target');

 

    var projection = myMap.options.get('projection');

    var position = geoObject.geometry.getCoordinates();

    var positionpx = myMap.converter.globalToPage(position);

 

    myMap.setGlobalPixelCenter([positionpx[0], positionpx[1]]);

 

}, this);

 

но....все еще есть смещение Т_Т

откуда оно взялось - не понятно

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

    var geoObject = e.get('target');

 

    var projection = myMap.options.get('projection');

    var position = geoObject.geometry.getCoordinates();

    var positionpx = projection.toGlobalPixels(position);

 

    myMap.setGlobalPixelCenter([positionpx[0] + 10, positionpx[1] + 10]);

 

}, this);

хм...при нажатии все точки пропадают с карты о_о

О_О Тут без ссылки не разобраться

как проект запустится, обязательно покажу :)

сделал ^^

вот так можно красиво прибить плейсмарк с большим баллуном к низу карты:

 var geo = placemark.geometry.getCoordinates(),

       projection =  map.options.get('projection'),

       globalPixel = projection.toGlobalPixels(geo, map.getZoom()),

       size = map.container.getSize();

map.panTo(projection.fromGlobalPixels([globalPixel[0], (globalPixel[1] - size[1]/2 +10) ], map.getZoom()),

                    {delay: 0});

placemark.balloon.open();

 

посмотреть тут http://www.pomnivoinu.ru/map/index1.php (клик на любой маркер - "подробно")

хм....я тоже потом понял что надо использовать panTo() для плавности о_о

после выходных допилю и выложу :)

upd. иногда валится ошибка.

наверное, лучше так:

            map.panTo(projection.fromGlobalPixels([globalPixel[0], (globalPixel[1] - size[1]/2 +10) ], map.getZoom()),

                    {delay: 0, callback: function() {

                self.placemark.balloon.open();

            }});