
Инструкция по использованию Яндекс.Карты с кластеризацией меток и динамическим обновлением
Шаг 1: Получение API-ключа Яндекс.Карт
Для работы с Яндекс.Картами необходимо получить API-ключ. Следуйте этим шагам:
- Перейдите на страницу получения ключа API Яндекс.Карт.
- Войдите в свой аккаунт Яндекса (если еще не зарегистрированы, создайте новый).
- Создайте новый API-ключ, следуя инструкциям на сайте.
- Скопируйте полученный ключ. Он понадобится для работы карты.

Шаг 2: Подключение Яндекс.Карт на страницу
Вставьте следующий код в раздел <head> вашего HTML-документа:
<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&apikey=ВАШ_API_КЛЮЧ" type="text/javascript"></script>
Замените ВАШ_API_КЛЮЧ на API-ключ, который вы получили на предыдущем шаге.
Шаг 3: HTML-разметка
Создайте контейнер, в котором будет отображаться карта:
<div id="yandex-map"></div>
Также, в вашем HTML должны быть карточки объектов, для которых вы хотите отображать метки на карте. Каждая карточка должна содержать атрибуты data-lat (широта) и data-lon (долгота), а также дополнительные атрибуты, которые будут отображаться в балуне карты.
Пример карточки:
<div class="map-objects-container"> <div class="map-object" data-lat="55.75" data-lon="37.62" data-title="Магазин 1" data-address="Москва, ул. Тверская, 1" data-phone="+7 (495) 123-45-67"></div> <div class="map-object" data-lat="55.76" data-lon="37.63" data-title="Магазин 2" data-address="Москва, ул. Арбат, 2" data-phone="+7 (495) 234-56-78"></div> </div>
Каждая карточка может содержать дополнительные атрибуты, такие как data-title, data-address, data-phone и т.д.
Шаг 4: Добавление JavaScript для инициализации карты и кластеризации меток
Вставьте следующий код JavaScript в файл или в конце HTML-документа перед закрывающимся тегом </body>:
document.addEventListener("DOMContentLoaded", function () { let observer = null; let map = null; // Переменные, которые можно настроить const containerSelector = ".map-objects-container"; // Контейнер с объектами const objectSelector = ".map-object"; // Класс объектов const mapContainerId = "yandex-map"; // Контейнер для карты // Конфигурация карты const mapOptions = { center: [55.751244, 37.618423], // Начальные координаты zoom: 5, // Начальный зум controls: ['zoomControl', 'geolocationControl'], // Контролы type: 'yandex#map', // Тип карты }; function initMap() { if (map) { map.destroy(); } map = new ymaps.Map(mapContainerId, mapOptions); // Определяем кастомный макет балуна ymaps.layout.storage.add('custom#balloonLayout', ymaps.templateLayoutFactory.createClass( `<div class="custom-balloon"> <div class="custom-balloon__content">$[properties.balloonContent]</div> <button class="custom-balloon__close">✖</button> </div>`, { build: function () { this.constructor.superclass.build.call(this); document.querySelector('.custom-balloon__close').addEventListener('click', () => { this.getData().geoObject.balloon.close(); }); } })); addMarkers(); } function addMarkers() { map.geoObjects.removeAll(); let objects = document.querySelectorAll(`${containerSelector} ${objectSelector}[data-lat][data-lon]`); let coordinates = []; const clusterer = new ymaps.Clusterer({ preset: 'islands#invertedRedClusterIcons', groupByCoordinates: false, zoomMargin: 100, clusterDisableClickZoom: false }); objects.forEach(function (object) { let lat = parseFloat(object.getAttribute("data-lat")); let lon = parseFloat(object.getAttribute("data-lon")); let title = object.getAttribute("data-title") || "Без названия"; let address = object.getAttribute("data-address") || "Адрес не указан"; let phone = object.getAttribute("data-phone") || "Телефон не указан"; if (!isNaN(lat) && !isNaN(lon)) { let placemark = new ymaps.Placemark([lat, lon], { balloonContent: ` <strong>${title}</strong><br> <span class="balloon-address">${address}</span><br> <span class="balloon-phone">${phone}</span> ` }, { balloonLayout: 'custom#balloonLayout' }); clusterer.add(placemark); coordinates.push([lat, lon]); } }); map.geoObjects.add(clusterer); if (coordinates.length > 0) { let bounds = getBounds(coordinates); map.setBounds(bounds, { checkZoomRange: true }); } else { map.setCenter(mapOptions.center, mapOptions.zoom); } } function getBounds(coordinates) { let latitudes = coordinates.map(coord => coord[0]); let longitudes = coordinates.map(coord => coord[1]); let minLat = Math.min(...latitudes); let maxLat = Math.max(...latitudes); let minLon = Math.min(...longitudes); let maxLon = Math.max(...longitudes); return [[minLat, minLon], [maxLat, maxLon]]; } const objectsContainer = document.querySelector(containerSelector); if (objectsContainer) { observer = new MutationObserver(debounce(initMap, 500)); observer.observe(objectsContainer, { childList: true, subtree: true }); } function debounce(func, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } initMap(); });
Шаг 5: Обновление карты при изменении данных
Если данные о дилерах изменяются динамически (например, через фильтры или асинхронную загрузку контента), карта будет автоматически обновляться. Для этого используется MutationObserver, который отслеживает изменения внутри контейнера .map-objects-container.
Дополнительные настройки
- Метки: Вы можете добавить любые атрибуты в карточки дилеров (например, data-email, data-rating, data-description) и использовать их для отображения в балуне или в другом месте на карте.
Комментарии пользователей (0)