Динамическая загрузка содержимого балуна
Часто при работе с картой приходится загружать большой объем дополнительных данных (текстовая информация, картинки и пр.). При этом загруженная информация не всегда используется пользователем. Например, когда на карте отображены сотни меток, и балун каждой из них содержит большой объем текста. При работе с картой пользователь может не открыть ни один балун, но данные все равно будут загружены.
В таких случаях в целях экономии трафика имеет смысл загружать данные не сразу, а по мере необходимости.
Данный пример демонстрирует динамическую загрузку содержимого балуна с помощью AJAX-запроса.
При клике на значок кластера или одиночной метки производится проверка, загружено ли содержимое их балуна. Если для каких-либо меток текст балуна не задан, серверу отправляется POST-запрос с массивом идентификаторов этих меток. Сервер обрабатывает массив и на его основе возвращает JSON-объект, содержащий необходимые данные.
Обратите внимание, что серверную часть необходимо реализовать самостоятельно.
<!DOCTYPE html>
<html>
<head>
<title>Динамическая загрузка содержимого балуна</title>
<meta
http-equiv="Content-Type"
content="text/html; charset=utf-8"
/>
<!--
Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
-->
<script
src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&apikey=<ваш API-ключ>"
type="text/javascript"
></script>
<script
src="https://yandex.st/jquery/2.2.3/jquery.min.js"
type="text/javascript"
></script>
<script src="om_balloon_ajax.js" type="text/javascript"></script>
<style>
html,
body,
#map {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>
ymaps.ready(function () {
var myMap = new ymaps.Map("map", {
center: [55.751574, 37.573856],
zoom: 10,
controls: [],
}),
objectManager = new ymaps.ObjectManager({
clusterize: true,
clusterDisableClickZoom: true,
});
myMap.geoObjects.add(objectManager);
objectManager.objects.events.add("balloonopen", function (e) {
// Получим объект, на котором открылся балун.
var id = e.get("objectId"),
geoObject = objectManager.objects.getById(id);
// Загрузим данные для объекта при необходимости.
downloadContent([geoObject], id);
});
objectManager.clusters.events.add("balloonopen", function (e) {
// Получим id кластера, на котором открылся балун.
var id = e.get("objectId"),
// Получим геообъекты внутри кластера.
cluster = objectManager.clusters.getById(id),
geoObjects = cluster.properties.geoObjects;
// Загрузим данные для объектов при необходимости.
downloadContent(geoObjects, id, true);
});
function downloadContent(geoObjects, id, isCluster) {
// Создадим массив меток, для которых данные ещё не загружены.
var array = geoObjects.filter(function (geoObject) {
return (
geoObject.properties.balloonContent ===
"идет загрузка..." ||
geoObject.properties.balloonContent === "Not found"
);
}),
// Формируем массив идентификаторов, который будет передан серверу.
ids = array.map(function (geoObject) {
return geoObject.id;
});
if (ids.length) {
// Запрос к серверу.
// Сервер обработает массив идентификаторов и на его основе
// вернет JSON-объект, содержащий текст балуна для
// заданных меток.
ymaps.vow
.resolve(
$.ajax({
// Обратите внимание, что серверную часть необходимо реализовать самостоятельно.
//contentType: 'application/json',
//type: 'POST',
//data: JSON.stringify(ids),
url: "content.json",
dataType: "json",
processData: false,
})
)
.then(function (data) {
// Имитируем задержку от сервера.
return ymaps.vow.delay(data, 1000);
})
.then(
function (data) {
geoObjects.forEach(function (geoObject) {
// Содержимое балуна берем из данных, полученных от сервера.
// Сервер возвращает массив объектов вида:
// [ {"balloonContent": "Содержимое балуна"}, ...]
geoObject.properties.balloonContent =
data[geoObject.id].balloonContent;
});
// Оповещаем балун, что нужно применить новые данные.
setNewData();
},
function () {
geoObjects.forEach(function (geoObject) {
geoObject.properties.balloonContent =
"Not found";
});
// Оповещаем балун, что нужно применить новые данные.
setNewData();
}
);
}
function setNewData() {
if (isCluster && objectManager.clusters.balloon.isOpen(id)) {
objectManager.clusters.balloon.setData(
objectManager.clusters.balloon.getData()
);
} else if (objectManager.objects.balloon.isOpen(id)) {
objectManager.objects.balloon.setData(
objectManager.objects.balloon.getData()
);
}
}
}
$.ajax({
url: "data.json",
}).done(function (data) {
objectManager.add(data);
});
});