Часто перед разработчиками сайта встаёт задача отразить на интерактивной карте местоположение каких-либо объектов. Например филиалов компании, магазинов, автозаправочных станций и т.д. Формировать карту в конструкторе яндекс карт каждый раз при появлении нового объекта — неудобно. Для решения этой задачи лучше воспользоваться API Яндекс карт и большими возможностями 1С Битрикс.
И так, разобьём работу на этапы:
- Установка продукта
- Подготовка инфоблока
- Подготовка компонента
- Внедрение JavaScript формирующего Яндекс карту
Установка продукта
Не стану подробно останавливаться на этом вопросе, думаю ни у кого он не вызывает трудностей. Дам лишь совет, пользоваться кодировкой UTF-8 она в любом случае выгоднее т.к. содержит больше символов нежели кирилица Windows (или windows-1251 стандартная битрикс кодировка). Кодировку можно указать во время установки продукта на 3-м шаге «Регистрация»:
Если на следующем шаге будут ошибки , обычно ругается на mbstring.func_overload и mbstring.internal_encoding в файл .htaccess в папке с устанавливаемой CMS укажите следующие директивы и продолжайте установку:
php_value mbstring.func_overload 2
php_value mbstring.internal_encoding UTF-8
На этом всё, переходим к настройке информационного блока.
Подготовка информационного блока
Давайте определимся что мы хотим получить. Допустим у нас есть несколько магазинов которые мы хотим показывать на интерактивной яндекс карте + давать пользователям какую-нибудь доп. информацию о них, например точный адрес магазина, часы работы, контактный телефон и ФИО руководителя. Т.е. по клику на точку на яндекс карте, мы увидим некий блок, так называемый балун с доп. информацией о магазине. Для формирования самой точки на карте, нам потребуется задавать её координаты, для этого в 1С Битрикс существует тип поля привязка к Яндекс карте.
Приступим! Создаём инфоблок «Магазины&qout; со следующими свойствами (Имя свойства — тип — мнемонический код):
- Адрес магазина — тип строка — ADDRESS
- Часы работы — тип строка — HOURS
- Контактный телефон — тип строка — PHONE
- ФИО руководителя — тип строка — SHOP_MANAGER
- Координаты — тип привязка к яндекс карте — YANDEX_MAP

Сохраняем инфоблок и добавляем в него несколько элементов, я добавил 3 магазина с 3-мя адресами в разных районах города Ростов-на-Дону. Важно при добавлении магазинов указать адрес на интерактивной карте Яндекс и сделать двойной щелчёк по заданной точке, чтобы заполнились поля координат точки иначе не получится построить точку на карте.

Добавив несколько элементов переходим к следующему этапу.
Подготовка компонета
Для реализации задумки я решил использовать компонент bitrix:news.list, с его помощью мы выведем на экран список магазинов, данные для формирования карты и контейнер для самой карты. Для того чтобы JavaScript смог построить интерактиыную карты, ему нужно отдать данные объектов, т.е. данные наших магазинов. Для этого есть 2 способа.
- Вывести данные оъектов в специальные атрибуты тегов, т.е. непосредственно в DOM дерево документа
- Подготовить структурированный массив в php и затем с помощью функции 1С Битрикс PhpToJSObject преобразовать массив в JavaScript объект и затем работать с этим JS обектом вытаскивая данные для формирования карты.
Лично я предпочитаю первый способ, т.к. считаю его более наглядным и понятным. И так скопируем компонент news.list в текущий шаблон сайта с помощью интерфейса «Эрмитаж» и укажем следующий код шаблона:
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
<div class="shop-list">
<?
$index = 1; // Порядковый номер объекта на карте
foreach($arResult["ITEMS"] as $arItem) { ?>
<?
$this--->AddEditAction($arItem['ID'], $arItem['EDIT_LINK'], CIBlock::GetArrayByID($arItem["IBLOCK_ID"], "ELEMENT_EDIT"));
$this->AddDeleteAction($arItem['ID'], $arItem['DELETE_LINK'], CIBlock::GetArrayByID($arItem["IBLOCK_ID"], "ELEMENT_DELETE"), array("CONFIRM" => GetMessage('CT_BNL_ELEMENT_DELETE_CONFIRM')));
?>
<?
//Разбиваем координаты яндекс карты на X и Y координату
$Yandex = explode(",", $arItem["PROPERTIES"]["YANDEX_MAP"]["VALUE"]);
$Yandex_X = $Yandex[0];
$Yandex_Y = $Yandex[1];
?>
<!--Засовываем данные для формирования точки на карте в атрибуты контейнера div-->
<div class="shop-data" data-index="<?=$index?>" data-name="<?=$arItem[" name"]?>"
data-yandex-x="<?=$Yandex_X;?>"
data-yandex-y="<?=$Yandex_Y;?>"
data-address="<?=$arItem["PROPERTIES"]["ADDRESS"]["VALUE"];?>"
data-hours="<?=$arItem["PROPERTIES"]["HOURS"]["VALUE"];?>"
data-phone="<?=$arItem["PROPERTIES"]["PHONE"]["VALUE"];?>"
data-shop-manager="<?=$arItem["PROPERTIES"]["SHOP_MANAGER"]["VALUE"];?>"
>
<!--Выводим информацию для пользователя-->
<b><?=$arItem["NAME"]?></b>
<ul>
<li><b>Адрес:</b> <?=$arItem["PROPERTIES"]["ADDRESS"]["VALUE"];?></li>
<li><b>Часы работы:</b> <?=$arItem["PROPERTIES"]["HOURS"]["VALUE"];?></li>
<li><b>Контактный телефон:</b> <?=$arItem["PROPERTIES"]["PHONE"]["VALUE"];?></li>
<li><b>ФИО руководителя:</b> <?=$arItem["PROPERTIES"]["SHOP_MANAGER"]["VALUE"];?></li>
</ul>
</div>
<? ++$index; } unset($index); ?>
<!--Контейнер в который прилетит сформированная яндекс карта-->
<div id="map_container"></div>
</div>
Давайте так же заранее пропишем css стили для контейнера карты, и точек (маркеров) на самой карте
#map_container {
width:100%;
height:600px;
display:block;
}
.marker-circ {
color: #404040;
font-size: 14px;
font-weight: normal;
height: 80px;
line-height: 56px;
width: 58px;
}
.claster {
color: #ffffff;
font-size: 14px;
font-weight: bold;
height: 80px;
line-height: 56px;
width: 58px;
}
Компонент готов, можно переходить к подключению JavaScript сформирующего нам яндекс карту.
Внедрение JavaScript Яндекс карты
Первым делом подключаем JQuery (в моём случае это jQuery v1.9.1) и скрипт яндекс карты, чтобы не держать лишьних скриптов на сервере можно воспользоваться удалёнными файлами.
<script src="http://yandex.st/jquery/1.9.1/jquery.min.js"></script>
<script src="http://api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
Затем в отдельном JavaScript файле (назовём его start.js), куда мы будем выносить все наши скрипты (чтобы не писать их прям в DOM дереве документа) пишем код:
$(document).ready(function () {
//Если на странице есть контейнер для яндекс карты с id map_container, начинаем её формировать
if ($("#map_container").length > 0) {
//yandex map
ymaps.ready(function () {
var map = new ymaps.Map("map_container", {
center: [47.223572, 39.725845], //Создаём карту с центром в городе "Ростов-на-Дону"
zoom: 11, //Увеличение 11
});
//Кластера - группируем близко расположенные друг к другу объекты, чтобы при отдалении карты появлялась другая иконка
// с количеством объектов в данной точке
var ClusterContent = ymaps.templateLayoutFactory.createClass('<div class="claster">$[properties.geoObjects.length] шт.</div>');
//Параметры иконки кластера, обычно её делают отличной от точки, чтобы пользователь не путал номер объекта
// и количество объектов
var clusterIcons = [{
href: '/bitrix/templates/furniture_pale-blue/images/map-claster.png',
size: [58, 80],
offset: [-24, -80],
}];
//Создание самого кластера
myClusterer = new ymaps.Clusterer({
clusterIcons: clusterIcons,
clusterNumbers: [1],
zoomMargin: [30],
clusterIconContentLayout: ClusterContent
});
//HTML шаблон балуна, того самого всплывающего блока, который появляется при щелчке на карту
var myBalloonLayout = ymaps.templateLayoutFactory.createClass(
'<address class="address-map">' + '
< p > < strong > $[properties.name] < /strong>'+ '
<br/>
'+ ' < /p>
<ul class="balloon-info">'+ '
<li><strong>Адрес: </strong>$[properties.address]</li>
'+ '
<li><strong>Часы работы: </strong>$[properties.hours]</li>
'+ '
<li><strong>Телефон: </strong>$[properties.phone]</li>
'+ '
<li><strong>Руоководитель: </strong>$[properties.manager]</li>
'+ '</ul>
'+ ' < /address>'
)
;
var Placemark = {}; //Пустой объекта, куда будут помещены точки на для карты
//Перебираем все блоки с картой и считываем данные для формирования точки и балуна по ранее заданному шаблону
$(".shop-data").each(function () {
//Координаты точки
var X = $(this).attr("data-yandex-x");
var Y = $(this).attr("data-yandex-y");
Obj = $(this).attr("pointindex");
//Создаём объект с заданными координатами и доп.свойствами
Placemark[Obj] = new ymaps.Placemark([X, Y], {
name: $(this).attr("data-name"), //Наименование магазина
address: $(this).attr("data-address"), //Адрес
hours: $(this).attr("data-hours"), //Часы работы
phone: $(this).attr("data-phone"), //Контактный телефон
manager: $(this).attr("data-shop-manager"), //Руководитель
iconContent: "<div class="marker-circ">"+$(this).attr("data-index") + "</div>", //Порядковый номер на карте
}, { //Ниже некоторые параметры точки и балуна
balloonContentLayout: myBalloonLayout,
balloonOffset: [5, 0],
balloonCloseButton: true,
balloonMinWidth: 450,
balloonMaxWidth: 450,
balloonMinHeught: 150,
balloonMaxHeught: 200,
iconImageHref: '/bitrix/templates/furniture_pale-blue/images/map.png', //Путь к картинке точки
iconImageSize: [58, 80],
iconImageOffset: [-24, -80],
iconLayout: 'default#imageWithContent',
iconactive: '/bitrix/templates/furniture_pale-blue/images/map-a.png' //Путь к картинке точки при наведении курсора мыши
});
//Добавляем маркер (точку) через кластер
myClusterer.add(Placemark[Obj]);
});
//Добавление кластеры на карту
map.geoObjects.add(myClusterer);
//Запрещаем изменение размеров карты по скролу мыши
map.behaviors.disable("scrollZoom");
});
}
});
Картинки для точек на карте я скачал с сайта www.iconfinder.com — это зарубежный поисковик по иконкам, многие из которых можно скачать абсолютно бесплатно, что я собственно и сделал. А на этом сервисе от яндекса удобно получать координаты точек и центра карты.
Если Вы всё сделали правильно у Вас должна получиться вот такая карта:
Если что-то не получилось, можете ознакомиться с исходниками. Желаю удачи!
А как сделать список объектов карты сделать активным как тут в апи: https://tech.yandex.ru/maps/jsbox/2.1/object_list там пример без кластера
Можете JSON собрать с объектами из данных инфоблока так как описано в groups.js. Что у вас не получается?
Не работает в 18 версии битрикса!!!!
Что конкретно не работает? У вас яндекс карта не запускается или что? В статье описано использование функционала битрикса который не менялся в 18-й версии. Если у вас не работает карта, убедитесь что вы получили api ключ, сейчас он обязательный как для коммерческого так и для бесплатного использования яндекс.карт. Без api ключа карта может не работать без явных ошибок в консоли. Общались на этот счёт с ребятами из яндекса в декабре прошлого года.
Здравствуйте, почему то тут пуста и метки непонятно где
Вы были правы - нужно было через ядро скрипты подключить. Все работает - отличный метод, спасибо!
Очень полезная статья, огромное спасибо. Но есть вопрос, почему задваевается сформированная карта, получается одна карта располагается как бы над другой, и все метки встают только на нижнюю карту, на верхней их не видно, только номера, хотя балуны срабатывают на обоих картах.
Я думаю у вас просто ошибка в оформлении, проверьте CSS тех блоков в которые вы размещаете яндекс карту.
Что касается пути, то он выглядит так. iconImageHref: '/images/map.png', //Путь к картинке точки И можно буквально пару слов о подключении скриптов? Спасибо вам огромное за решение. Давно искал.
Я имел ввиду у вас картинка открывается по этому пути (в браузере #ваш_сайт#/images/map.png )? По скриптам всё в доках есть https://dev.1c-bitrix.ru/api_help/main/reference/cmain/addheadscript.php , рекомендую так же к прохождению курс https://academy.1c-bitrix.ru/training/course/5862/ , там все эти вопросы подробно раскрываются.
Ok. Цифры на карту выводятся. Картинки из браузера доступны. Если нажать на цифру - данные видно. Кластеризация отрабатывает - пишет при масштабировании "2 шт.". Значит скрипт отрабатывает. Но метки все равно не видно. Куда еще можно капнуть?
Даже не знаю, надо смотреть конкретно.
Отличная статья, большое спасибо! Возможно не много не по теме кластеризации, но относящийся к картам. Подскажите пожалуйста, как можно настроить Поиск по свойствам? Например выводить форму с чекбоксами, которые в свою очередь проверяют 0 или 1, Да или Нет и т.д. и убирают\добаваляют точки на карту, без перезагрузки страницы.
Ну смотрите, делайте вначале обычную формы с перезагрузкой, если речь идёт о битриксе вот тут можно посмотреть самую простейшую реализацию фильтра (без использования компонента). Получили фильтр с перезагрузкой страницы - отлично, дальше навешиваем jquery ajax, т.е. по кнопке "фильтровать" (или при нажатии на чекбокс) отправляем данные через POST на эту же страницу (смотрите jquery change()). Результат запроса обрабатываете в jquey ajax, там (в ajax ответе, обычно это переменная $(data)) находите контейнер с картой, функцией jquery html() получаете его содержимое и заменяете им содержимое текущего контейнера и перезапускаете карту. Пример реализации можно глянуть тут vertikal-invest.ru файл script.js
Понял, буду пробовать, спасибо. Просто я как вижу js, так сразу начинается паника. И у меня еще один вопрос. При максимальном увеличении карты, все ок, но как только начинаю отдалять, точки начинают съезжать на встречу друг к другу, видать для того, что бы потом объединиться. Как это можно убрать? Кластеризация пускай остается, но точки при этом не ездили бы на встречу друг к другу, оставались статично на одном месте. Спасибо.
Чтобы js-а не бояться посмотрите этот курс, я после него стал js понимать. Маркеры на карте всёравно будут съезжаться, они должны в кластеры собираться (смотрите решение тут vertikal-invest.ru), это нельзя убрать (если правильно понял о чём вы говорите), это работают скрипты яндекса, api карт.
Странно. Вроде все по инструкции, а карта не работает. И еще данные о скрипте где то в кэш падают. Пока не переименуешь имя файла изменения в коде не работают. Словом выводится список элементов, под списком карта, а на карте только цифры вместо меток. Помогите кто нибудь пожалуйста...
Вот скрин https://yadi.sk/i/XI2l5jG73Jcxxb
Во первых проверьте правильность путей к картинкам, это параметры в скрпте iconImageHref и iconactive , прямо откройте их в браузере и посмотрите что покажет Что касается кеша, думаю вы подключили скрипты напрямую, а надо через ядро с использованием метода $APPLICATION->AddHeadScript(), тогда с кешем проблем не будет.
Точнее вот этот кусок https://yadi.sk/i/bCm_p8JR3Jcykk
Убрал вот этот кусок Адрес: Часы работы: Контактный телефон: ФИО руководителя: Список пропал. На карте данные есть. Только не работает оформление меток.
За курс спасибо, обязательно ознакомлюсь. На сайте как раз все отлично с метками, они съезжают из-за уменьшения размера карты(при этом точки остаются прежнего размера) из-за этого как бы и съезжают. У меня есть точка, расположение ее находится в Москве, если я максимально отдаляю, точка идет почти на северный полюс. Если я от максимально приближенного размера два-четыре раза отдалю, то точка перепрыгивает на соседнюю улицу(постепенно с каждым кликом все выше и выше).
Подскажите, куда лучше вставить start.js? В шаблон страницы или шаблон компонента?
А это уже как вам будет удобнее. Я например всё в шаблоне сайта храню, чтобы не искать скрипты по компонентам.
Добрый день. Сделали данную штуку у себя на портале Битрикс, менеджеры заводят объекты, они отображаются на карте, руководитель видит работу менеджера
. Ну буквально месяц назад, перестала отображаться карта, объекты заводятся все хорошо, но на странице форматирования карты пустой контейнер. Вопрос, а в данной карте есть ограничения по количеству объектов на карте? Если нет, что могло случится предположительно, доступа к админке Битрикс ни у кого нет блок новостей не правился..
Никаких ошибок JS не выдаёт? По идеи ограничений нет, возможно что у самого яндекса что-то поменялось, но вы бы наверняка увидели бы ошибки в консоли (F12 в Chrome), а может яндекс затребовал ключ доступа (возможно есть ограничения на использования API яндекс карт без ключа, token, возможно яндкес посчитал что у вас какое-то коммерческое приложение с кучей объектов на карте). Я бы написал в яндекс.
Все получилось. Спасибо. Очень полезный материал. подскажите как убрать нумерацию у точек?
iconContent: ""+$(this).attr("data-index")+"" - надо $(this).attr("data-index") убрать помоему =)
либо выводит список элементов инфоблока, карту снизу и все.
Ну вы скорее всего поместили в цикл создание самой карты, проверьте чтобы объект var map = new ymaps.Map("map_container") у вас создавался один (причём map_container - id единственного элемента, проверте чтобы map_container был один в html), так же выведите в консоль Placemark, точки на карте, что туда попадает. Конкретней сказать не могу, надо код смотреть =)
Здравствуйте вывдит не одну а кучу карт, то есть для каждого элемента инфоблока. а не одну общую карту для всех
Добрый день. Спасибо за решение. Подскажите пожалуйста, а как сделать, чтобы карта появлялась не (center: [47.223572, 39.725845], //Создаём карту с центром в городе "Ростов-на-Дону"), а по координатам элемента. Поясню: создан ИБ - Россия - Санкт-Петербург, Москва, Ростов-на-Дону и т.д. с магазинами в этих городах и прописанными координатами. Сейчас открывается карта с центром прописанных координат в JS, а мне нужно чтобы она открывалась по координатам при нажатии на Москва, Ростов-на-Дону, Санкт-Петербург и т.д. центровалась по этим регионам. Москва - список магазинов - Карта с центровкой Москвы. И также при нажатии на другие регионы. Спасибо.
Создайте доп.свойста у ИБ куда пропишите координаты нужных городов, а дальше аналогично (data-yandex-x, data-yandex-y) нужно вывести эти координаты в отдельный контейнер (какой-нибудь невидимый span с data-атрибутами) и считав из него значения подстваить их в атрибут center: [коордианты вашего города].
Интересное решение - очень помогло в одном проекте. Но есть вопрос: А как реализовать 2 разных вида метки, например с мощью управления из инфоблока. Допустим отметил чекбокс в инфоблоке и данный элемент вывелся с другой картинкой меткой? Я естественно не лажу с API Яндекса и js в принципе ...
Ну смотрите, данные для формирования карты у меня передаются в DOM (т.е. в атрибуты тегов). откуда я их потом считываю js скриптом и запускаю карту. В параметрах скрипта в моём примере картинка маркера (точки) определена заранее "iconImageHref: '/bitrix/templates/furniture_pale-blue/images/map.png', //Путь к картинке точки" - но вы можете вместо "/bitrix/templates/furniture_pale-blue/images/map.png" подгружать свою картинку из атрибута тега. Т.е. в инфоблоке ставим радиобокс "картинка 1", "картинка 2" в зависимости от галочки в в какой-нибудь атрибут тега (например data-markerimage) выводим путь к картинке. ну а в js соответственно считываем его как в свойство "iconImageHref: $(this).attr('data-markerimage')" или так "iconImageHref: $(this).data('markerimage')". Вуаля =)