Продолжим знакомство с API «Рамблер-Карт», и на этот раз разберёмся с кластеризацией меток.
Когда на одном участке карты сосредоточено слишком много меток, они накладываются друг на друга, закрывая значительные части карты. Сложно найти и выбрать среди них нужные. Да и в целом, это выглядит не слишком аккуратно.
Бороться с этой проблемой можно при помощи метода makeCluster, который объединяет метки в кластеры и оставляет на карте лишь кластерные метки, на которых указано количество объединённых точек.
Для примера рассмотрим метки московских аптек на карте до кластеризации и после.
Чтобы создать множество меток, воспользуемся методом геокодирования search с поисковым запросом «аптека». По координатам, взятым из найденных результатов, построим метки (построим их исключительно ради наглядности примера «до-и-после» — вообще говоря, для создания кластера достаточно массива координат, в этом вы убедитесь чуть позже).
var pharmacies = map.search("аптека", function(err, data, transport){
//объявляем массив координат
var coordArray = [];
//объявляем массив меток
var markerArray = [];
//и заполняем эти массивы
var items = data.res[0].matches //массив результатов
for ( var i=0, item; item=items[i]; i++){
//извлекаем координаты из найденных результатов
coordArray[i] = {
lon: item.x,
lat: item.y
};
//создаём метки
markerArray[i] = map.geometry.create("marker", {
coord: coordArray[i]
})
}
Теперь дело за малым. Массив меток найденных аптек разбиваем на кластеры.
//кластеризуем массив координат (если передать в качестве аргумента массив меток markerArray, получим в точности то же самое)
var cl = map.makeCluster(coordArray, {
area: "hull" // устанавливаем выделение площади кластера — в виде оболочки
//и используем CSS, чтобы изменить внешний вид кластерных меток, заданный по умолчанию
clusterMarker: {
"class": "",
html: '<div style= "background:#9B2D30; border:1px solid #FFF; color:#FFF; padding:5px ">${quantity}</div>'
}
});
console.log(cl);
});
Готово
Исходный код примера доступен по ссылке: maps.rambler.ru/api/examples/TutorialClusterize.html
P.S.
Несколько слов об алгоритме кластеризации. Мы используем Quadtree: карта на самом маленьком масштабе (уровень масштабирования = 1) делится на 4 квадрата, каждому из которых присваивается номер: 0, 1, 2, 3. На следующем уровне масштабирования каждый из этих квадратов вновь делится на 4 квадрата. 16 новых квадратов нумеруются в соответствии с принадлежностью к большим: 00, 01, 02, 03, 10, 11, …, 44. Операция деления квадратов на 4 более мелких повторяется до некоего уровня масштабирования n, на котором, соответственно, уже будет 4^n квадратов, каждый из которых имеет уникальный n-значный номер.
Зная номер квадрата, можно определить, где он находится на карте и на каком масштабе. Метки, оказывающиеся на одном таком квадрате, образуют кластер.
Передавая в аргументах метода параметр maxZoom, мы указываем, на каком масштабе следует прекратить объединять метки в кластеры и начать показывать их раздельно (то есть каждую на своём месте). Фактически, maxZoom и есть выше упомянутое число n.
Автор: 127