Клуб API Карт

Открыть балун по координатам

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

Привет всем!

Есть карта с множеством плейсмарков, при клике на которые можно посмотреть их содержимое, например http://www.citilink.ru/route/ нижняя карта.

Вопрос в следующем: как при определённом событии открыть балун, если я знаю координаты точки и балун находится уже на карте?

Что-то вроде этого:

$('a.showBalloon').click(function(e){
   e.preventDefault();
   var chords = 'тут координаты плейсмарка, который уже на карте';
   map.setCenter(chords, 15);
   //что тут написать, чтобы просто открыть балун этой точки?
});

10 комментариев
Sergey Konstantinov
28 января 2016, 03:26

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

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

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

Удалённый пользователь
28 января 2016, 03:26

Спасибо. Это понятно...

Просто я при получении меток в цикле ищу ближайшее метро сл образом:

var map3;

map3 = new YMaps.Map(document.getElementById('map3'));

map3.setCenter(new YMaps.GeoPoint(37.62,55.77), 10);

var placemark = new Array();

var point = new Array();

var obj, mName;

for(var i=0;i

{

 point[i] = new YMaps.GeoPoint(pupX[i], pupY[i]);

 placemark[i] = new YMaps.Placemark(point[i]);

 placemark[i].setIconContent(i+1);

 placemark[i].description = ''+pupName[i]+''+'
Адрес: '+pupAdr[i]+'
Телефон: '+pupPhone[i]+'
Время работы: '+pupTime[i]+'
подробнее';

 var curMetro = new YMaps.Metro.Closest(new YMaps.GeoPoint(pupX[i],pupY[i]), { results : 1 } );

YMaps.Events.observe(curMetro, curMetro.Events.Load, function(curMetro) {

if (curMetro.length()) {

obj = curMetro.get(0);

mName = obj.text.split('метро');

$("#metroMap a").each(function(){

if ($.trim($(this).attr('title')) == $.trim(mName[1])) {

$(this).css('display', 'block');

$(this).attr('id', curMetro.request);

return false;

}

});

}

});

YMaps.Events.observe(curMetro, curMetro.Events.Fault, function (curMetro, error) {

alert("При выполнении запроса произошла ошибка: " + error);

});

}

map3.addOverlay(placemark[i]);

map3.addControl(new YMaps.Zoom());

 

Тоесть, если ближайшая точка найдена, я должен добавить плейсмарк в массив, но проблема в том, что в обработчике Load никакие переменные не видны. Хотя если поставить break после первой итерации и вывести placemark[i].description например, то всё нормально отобразиться, а если убрать break и позволить циклу пройти до конца, то при загрузке страницы в концоле firebug'a, будет много ошибок: TypeError: placemark[i] is undefined.

Я не сильно силён в яваскрипте, может это какая-то особенность?

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

Sergey Konstantinov
28 января 2016, 03:26

Это типичная ошибка начинающих изучать JavaScript.

Вам нужно поймать переменную в замыкание, например вот так:

for(var i=0;i

function getMetro (n) {

  var curMetro = new YMaps.Metro.Closest(new YMaps.GeoPoint(pupX[n],pupY[n]), { results : 1 } );

  YMaps.Events.observe(curMetro, curMetro.Events.Load, function(curMetro) {

    alert(n); // Здесь n останется равным индексу метки, для которой выполнялся поиск

  });

}

Вот хорошая книжка по js: http://javascript.ru/book/definitiveguide

Удалённый пользователь
28 января 2016, 03:26

Интересно) Спасибо, прочту про это замыкание.

Вынес по вашему совету в отдельную функцию, но теперь пишет, что TypeError: pupX is undefined

 

 for(var i=0;i

 {

  point[i] = new YMaps.GeoPoint(pupX[i], pupY[i]);

  placemark[i] = new YMaps.Placemark(point[i]);

  placemark[i].setIconContent(i+1);

  placemark[i].description = ''+pupName[i]+''+'
Адрес: '+pupAdr[i]+'
Телефон: '+pupPhone[i]+'
Время работы: '+pupTime[i]+'
подробнее';

 getMetro(i);

 }

 map3.addOverlay(placemark[i], pupX, pupY);

 map3.addControl(new YMaps.Zoom());

 

Пробовал передавать остальное в функцию: getMetro(i, pupX, pupY), но вылезает такая же ошибка (

По идеи pupX и pupY объявлены глобально.

Sergey Konstantinov
28 января 2016, 03:26

Функцию getMetro можно объявить прямо там же, перед циклом или после цикла, например.

JS поддерживает объявления функций любой вложенности.

 

Удалённый пользователь
28 января 2016, 03:26

Пробовал перенести функцию до цикла, всё равно не работает :(

Sergey Konstantinov
28 января 2016, 03:26

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

Удалённый пользователь
28 января 2016, 03:26

Понимаю)))

Я чуть-чуть приблизился к сути.

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

 

YMaps.Events.observe(curMetro, curMetro.Events.Load, function(curMetro) {

if (curMetro.length()) {

obj = curMetro.get(0);

//alert(i) покажет 0-1-2-3-4 и тд

mName = obj.text.split('метро');

$("#metroMap a").each(function(){

//alert(i) показывает всегда 51, тоесть длину totalPoints

if ($.trim($(this).attr('title')) == $.trim(mName[1])) {

$(this).css('display', 'block');

$(this).attr('id', i);

plMetro[i] = {'chords': curMetro.request, 'mark': placemark[i]};

return false;

}

});

}

});

 

Тоесть внутри функции each переменная i всегда равна финальному значению...

 

Тоесть внутри функции each переменная i всегда равна финальному значению...

прочитайте уже про замыкания

Удалённый пользователь
28 января 2016, 03:26

Разобрался!

Надо было замкнуть)))

var obj, mName, ret, curMetro = new YMaps.Metro.Closest(new YMaps.GeoPoint(pupX[i],pupY[i]), { results : 1 } );

(function(i){

YMaps.Events.observe(curMetro, curMetro.Events.Load, function(curMetro) {

if (curMetro.length()) {

obj = curMetro.get(0);

mName = obj.text.split('метро');

$("#metroMap a").each(function(){

if ($.trim($(this).attr('title')) == $.trim(mName[1])) {

$(this).css('display', 'block');

$(this).attr('id', i);

plMetro[i] = {'chords': curMetro.request, 'mark': placemark[i]};

return false;

}

});

}

});

})(i);

Всем спасибо!!!)