Всем привет!
Это моя первая тема в клубе. Она посвящена выводу большого количества маркеров.
Ранее я использовал 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.marke
rs[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_mark
ers_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);
}
}