22 декабря 2015
28 декабря 2010
21
Яндекс.Карты, статья №3: Кластерер и большое количество маркеров
Всем привет!
Как вы помните, мы уже писали, что делать, если у вас получается много маркеров в Google Maps. Сегодня я хочу рассказать, что делать, если маркеров много на ваших Яндекс.Картах.
Сейчас я работаю над проектом, где мне нужно выводить много маркеров на карту, для которой используется API от Яндекс.Карт.
В процессе работы выяснилось, что для Яндекс.Карт, в отличии от Google Maps, готового кластерера нет. Поэтому мы написали свой, взяв за основу кластерер от Гуглокарт.
Предыстория
Как я уже сказал, в Яндекс.Картах нет встроенного механизма для кластеризации маркеров, как, собственно, и в Google Maps. Зато для карт Гугла есть куча плагинов, и есть из чего выбрать. В Яндекс.Картах же есть активные области и диспетчер объектов, но работа с ними у меня не заладилась.
В итоге я решил, что надо бы сделать кластерер для Яндекс.Карт. За основу был взят кластерер для Google Maps, который Женя Котельников, автор сервиса «Линчелка», переписал под API от Яндекс.Карт. За это ему отдельное спасибо ;-)
Кластерер для Яндекс.Карт
Подключаем Яндекс.Карты, затем сам кластерер:
<script type="text/javascript" src="http://api-maps.yandex.ru/1.1/index.xml?key="></script>
<script type="text/javascript" src="/js/map.yandex.clusterer.js"></script>
Создаем объект кластерера:
...
var cluster = new PlacemarkClusterer(map, null);
...
Добавляем в него маркеры (по одному или массивом):
...
cluster.addPlacemark(marker); // один маркер
...
cluster.addPlacemarks(markers); // сразу несколько
...
Теперь посмотрим на настройки для кластерера:
...
var cluster = new PlacemarkClusterer(map, null, {
gridSize: 60, // размер ячейки кластера
maxZoom: 16, // уровень зума, после которого показываются все маркеры
style: {
url: 'cluster.png', // адрес иконки группы маркеров кластера
height: 50, // высота
width: 50 // ширина
}
});
...
Для удаления маркера из кластера используется метод cluster.removePlacemark(placemark), а чтобы удалить все маркеры — cluster.clearPlacemarks():
...
cluster.removePlacemark(marker); // удалить указанный маркер из кластера
...
cluster.clearPlacemarkes(); // удалить все маркеры их кластера
...
Остальные методы можно посмотреть в самом файле. Скачать плагин можно ниже:
Есть идеи для улучшения? Вопросы? Пожелания?
Не забудьте рассказать друзьям о нашем плагине — красивые кнопочки сразу после статьи там именно для этого! Заранее спасибо!
По-моему он делает ровно то же самое, что вы написали.
Не понимаю привычки некоторых программистов на вопрос "а можно ли сделать так?" отвечать "лезь в исходники". Я ведь не требую фич, просто интересна идея.
Кстати, почему вы решили, что
Просто предполжение, тесты, статья какая-нить или в мануале написано?
Про кафешки, банки и парки. Да, нужно будет делать по отдельному объекту кластерера для каждого типа маркеров. Только не забудьте реализовать эти самые show, hide и isHidden для кастомных маркеров.
Планируется ли такая возможность для карт Яндекса?
Каждую итерацию
i
увеличивается на единицу и мы можем обратиться к соответствующему элементу массива. Результат будет такой:Я предлагаю почти такой же способ, но идти мы начинаем с последнего элемента.
Результат будет такой:
Такой способ можно использовать, когда нужен обратный порядок, или порядок не важен (например, нам нужно посчитать сумму всех элементов массива - начинать считать можно и с начала и с конца).
Механизм работы очень простой.
i = array.length
- присваиваем переменнойi
длину массива, в данном случае 4. Проверяем, не является ли это значение "нулевым". Если не является, но уменьшаем на единицу и выполняем блок кода. Таким образом, оно начнёт проходить с элементаarray.length-1
, а закончит элементом1-1
, то есть нулевым.Естественно, элементы массива удаляться не будут. Мы не меняем ни массив ни свойство
array.length
при клике на кластер происходит приближение к месту первой метки в кластере. и так до упора. постоянно видна пиктограмма кластера с неизменным кол-вом меток в нём. а самих меток так и не видно.
с чем это может быть связано?
после того как получаю нужные мне маркеры
я делаю так
clusterer.clearPlacemarks();
clusterer.addPlacemarks(markers);
так вот выше преведнные код вызывает у меня проблемы, которые я описал в предыдущем комменте
но если убрать строчку clusterer.clearPlacemarks(); то всё работает как надо
только вот мне всё же нужна после каждого нового запроса.. стирать старые маркеры
clusterer.clearPlacemarks();
clusterer = new PlacemarkClusterer(map, markers);
так же всё будет работать, если в Вашем плагине закомментить строчку
mcfn_.disable();
которая как, я понял, зачем-то отключает обновление вьюпорта при удалении всех маркеров, а при добавлении новых этого почему-то неделается.
может оно и логично, что нужно заново создавать объект clusterer, если очистил его полностью
а может я что-то не вкурил. не люблю в чужом коде копаться чёрт возьми