Динамическое содержимое в YMapsML

Очень удобно загружать свои данные на карту сформировав файл в формате YMapsML.

Мы можем формировать его динамически из записей в базе данных.

Для отображения информации в балуне используется шаблон.

Но иногда возникают проблемы, если мы имеем каждый раз различное число элементов для отображения в балуне метки.

Это может быть информация о маршрутах транспорта по остановкам со ссылками на отображения маршрута или число фотографий для объявлений о недвижимости и т. д.

Как же можно решить данную проблему?

В этой заметке я рассмотрю один из вариантов ее решения.

Суть его заключается в том, что мы будем разбирать данные из YmapsML-файла и добавлять к ним необходимый html-код для отображения в скрипте вывода карты.

Чтобы было все понятно рассмотрим небольшой пример.

У нас имеются данные о продаже квартир в Нижнем Новгороде с различным числом фотографий для каждого объявления, нужно вывести эти данные в виде меток на карту, используя YmapsML.

Я заранее сформировал YmapsML?файл с данными nedv-data.xml

В нем используется следующий шаблон для вывода данных в балуне:

<Template gml:id="balloonTemplate"> 
            <text><![CDATA[
			<div style="font-size:12px;"> 
                        <div style="color:#ff0303;font-weight:bold">$[name]</div>
						<div><strong>Тип объявления: </strong>$[metaDataProperty.AnyMetaData.type]</div> 	
                        <div><strong>Адрес: </strong>$[metaDataProperty.AnyMetaData.address]</div>
						 <div><strong>Район: </strong>$[metaDataProperty.AnyMetaData.rayon]</div>
						 <div><strong>Продавец: </strong>$[metaDataProperty.AnyMetaData.prodavec]</div>
                        <div><strong>Телефон: </strong>$[metaDataProperty.AnyMetaData.telephon]</div>  
						<div><strong>Тип жилья: </strong>$[metaDataProperty.AnyMetaData.typeflat]</div> 
						<div><strong>Кол-во комнат: </strong>$[metaDataProperty.AnyMetaData.roomnum]</div>
						<div><strong>Этаж: </strong>$[metaDataProperty.AnyMetaData.floor]</div>
						<div><strong>Всего этажей: </strong>$[metaDataProperty.AnyMetaData.floorfool]</div>
						<div><strong>Общая площадь кв.м: </strong>$[metaDataProperty.AnyMetaData.area]</div>
						<div><strong>Жилая площадь кв.м: </strong>$[metaDataProperty.AnyMetaData.livingspace]</div>
						<div><strong>Площадь кухни кв.м: </strong>$[metaDataProperty.AnyMetaData.kitchenarea]</div>
						<div><strong>Цена руб: </strong>$[metaDataProperty.AnyMetaData.price]</div>
						<div><strong>Подробнее: </strong>$[metaDataProperty.AnyMetaData.text]</div>
						<div><strong>Фото: </strong>$[metaDataProperty.AnyMetaData.foto|не задан]</div>						
                    </div>]]></text> 
        </Template>

Обычно для вывода YmapsML?файла используют следующий код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>YMapsML - отображение на карте</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script src="http://api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU"
            type="text/javascript"></script>
    <script type="text/javascript">
        // Как только будет загружен API и готов DOM, выполняем инициализацию
        ymaps.ready(init);
 
        function init () {
            var myMap = new ymaps.Map("map", {
                    center: [56.326944,44.0075], 
                    zoom: 12
                });
 
            // Загрузка YMapsML-файла
			ymaps.geoXml.load("http://webmap-blog.ru/xml/nedv-data.xml")
			.then(function (res) { // функция обрабатывает успешный результат получения YMapsML        
        myMap.geoObjects.add(res.geoObjects); // Добавление геообъектов на карту
    }, function (error) { // Вызывается в случае неудачной загрузки YMapsML
        console.error('Ошибка: ' + error);
});
        }
    </script>
</head>
 
<body>
 
    <div id="map" style="width:800px;height:600px"></div>
</body>
 
</html>

Посмотреть пример в действии

Единственная проблема это вывод фотографий, т. к. их число может быть различным.

В моем примере, сейчас в место фото выводиться их назвние.

Для вывода фотографий необходимо обработать данные из YmapsML?файла в скрипте вывода карты.

Посмотрим пример работы

А теперь рассмотрим его код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>YMapsML - отображение на карте</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script src="http://api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU"
            type="text/javascript"></script>
    <script type="text/javascript">
        // Как только будет загружен API и готов DOM, выполняем инициализацию
        ymaps.ready(init);
 
        function init () {
            var myMap = new ymaps.Map("map", {
                    center: [56.326944,44.0075], 
                    zoom: 12
                });
 
            // Загрузка YMapsML-файла
			ymaps.geoXml.load("http://webmap-blog.ru/xml/nedv-data.xml")
			.then(function (res) { // функция обрабатывает успешный результат получения YMapsML        
        myMap.geoObjects.add(res.geoObjects); // Добавление геообъектов на карту
    }, function (error) { // Вызывается в случае неудачной загрузки YMapsML
        console.error('Ошибка: ' + error);
});
        }
    </script>
</head>
 
<body>
 
    <div id="map" style="width:800px;height:600px"></div>
</body>
 
</html>

В этом коде в начале, мы получаем YMapsML методом geoXml.load, который возвращает вам объект-обещание (т.к. это асинхронный http-вызов), вызваваем у этого объекта метод then и передаемему в параметрах 2 функции.

В первой мы получем упорядоченную коллекцию геообъектов, перебирая элементы которой, мы можем получить доступ к данным геообъекта.

Используем item.properties.get.

Перед тем, как формировать код содержимого для балуна, мы обрабатываем данные о фотографиях.

Разбиваем строку на части по символу «,» и из полученного массива формируем код ссылки и вывода изображения.

Далее добавляем метки на карту.

Загрузить архив с файлами примера

Для заметки использовались материалы из Клуба разработчиков API Яндекс.Карт

  • Гость: Спасибо, как всегда замечательная статья! У меня коллекции разбиты на группы (чтобы каждой группе задать свой стиль) и видимо из-за этих групп возникает ошибка вот тут: res.geoObjects.each(function (item) { эту строчку надо как-то изменить?
  • Гость: Спасибо большое. Долго мучался с этим АПИ 2.0. Только вот не понятно одно. Мы в XML файле определяем шаблон, а по итогу вынуждены шаблон собирать заново в скрипте через конкатенацию balloonContentBody. Я так понимаю, что из XML можно выкинуть определение шаблона и просто динамически его создавать в скрипте?
  • Гость: как можно скрыть исходный файл ymaps.geoXml.load("http://webmap-blog.ru/xml/nedv-data.xml"), чтобы его не было видно? где-то видел, что XML файл был зашифрован в виде ymaps.geoXml.load("http://webmap-blog.ru/xml/e65151ac8262d01df.xml")
  • Гость: Скрыть его не получится, т.к он должен быть доступен парсеру Яндекса для обработки.
  • Гость: я как то видел вместо файла указано e65151ac8262d01df + видел реализацию через php