Клуб API Карт

вывод большого количества маркеров с помощью ObjectManager

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

Всем привет!

Это моя первая тема в клубе. Она посвящена выводу большого количества маркеров.

Ранее я использовал Google Maps, и в частности для вывода большого кол-ва маркеров я использовал MarkerManager, но для я.карт мне не попалось аналога, и я написал нужный код самостоятельно. (Ниже я его приведу, чтобы желающие смогли им воспользоваться.)

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

 На я.картах этого не происходит, что меня не вполне устраивает.

Мой вопрос к знатокам: как можно решить данную проблему, не отказываясь от ObjectManager?

Есть также еще одно пожелание. Очень бы хотелось получить некий гибрид из GeoObjectCollection и ObjectManager. У первого есть возможность скрывать/показывать группы маркеров, у второго есть возможность скрывать/показывать отдельные маркеры в зависимости от зума. А мне нужны обе эти возможности. Кто-нибудь знает, как можно этого добиться?

Далее публикую функцию, которая позволяет задавать минимальное расстояние между соседними маркерами, тем самым регулируя плотность маркеров. Алгоритм не идеальный, но простой и работающий. Если комментариев в коде недостаточно, буду рад ответить на вопросы. (Извиняюсь за то, что пока не могу опубликовать работающий пример. Постараюсь сделать это через несколько дней.)

function placeMarkers(hash){

/* 

на входе объект со следующими полями:

hash.markers - массив данных по маркерам (широта, долгота и пр.)

hash.min_distance_between_markers_px - минимальное расстояние в пикселах между соседними маркерами

hash.obj_manager - экземпляр YMaps.ObjectManager

hash.marker_style - объект со стилями маркера

*/

// проходим по массиву маркеров

for(var i=0; i<hash.markers.length; i++){

// создаем маркер

var placemark = new YMaps.Placemark(new YMaps.GeoPoint(hash.markers[i].lng, hash.markers[i].lat), {style: hash.marker_style});

// предполагаем, что мы будем показывать маркер при любом зуме

var min_zoom=0;

// первый маркер располагаем без каких либо проверок

if(i>0){

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

// среди всех предыдущих маркеров отыскивам ближайший к текущему

// для этого определяем переменную min_distance, как расстояние между текущим маркером и любым другим

// затем перебираем маркеры и обновляем min_distance при нахождении меньшего расстояния

var min_distance=null;

for(var j=0; j<i; j++){

var distance=placemark.getGeoPoint().distance(new YMaps.GeoPoint(hash.markers[j].lng,hash.markers[j].lat));

if(!min_distance){

min_distance=distance;

}else{

min_distance=Math.min(min_distance, distance);

}

}

// теперь зная расстояние до ближайшего маркера мы можем определить,

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

// между двумя маркерами не было меньше заданного минимума

for(var zoom=17; zoom>=0; zoom--){

var min_distance_between_markers_m=Math.pow(2,(17-zoom)) * hash.min_distance_between_markers_px * (2/3);

if(min_distance_between_markers_m > min_distance){

var min_zoom=zoom+1;

break;

}

}

}

// добавляем маркер с заданным минимальным зумом на карту

hash.obj_manager.add(placemark, min_zoom);

}

}

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

Насчет порядка отображения - placemark.setOptions (http://api.yandex.ru/maps/jsapi/doc/ref/reference/placemarkoptions.xml)
нужен zIndex который можно получить для прейсмарка как ЧТО-ТО - Yкоордината*что-то другое, ну например 18000-lat*100 (хотя вроде маловато будет)
Подходов много - особо углубляться не буду
Спасибо! Сейчас буду пробовать.
Привет..

а формула эта откуда? :)

var min_distance_between_markers_m=Math.pow(2,(17-zoom)) * hash.min_distance_between_markers_px * (2/3);

Отличный вопрос!

Формулу вывел эмпирическим путем. На 17 зуме 60 метров составляют 90 пикселов. Следовательно 1 пиксель есть 2/3 метра. С каждым шагом зума это расстояние удваивается.