Карта с точками на сайте - данные, вывод, фильтр по городу
Показываем магазины или пункты выдачи на карте: храним точки в инфоблоке, отдаём их скрипту карты и связываем список адресов с метками.
Решение
Точки - это обычные данные сайта, а не настройка карты. Держат их элементами инфоблока: название, адрес, координаты, часы работы, телефон и признак временного закрытия.
Заводим свойства точки:
$rows = CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId])->GetNext();// COORDS - строка вида "55.751244,37.618423", проще всего хранить одним свойством// PHONE, WORK_TIME, CITY - обычные строковые свойства и привязка к разделуКоординаты удобнее держать одним строковым свойством, а не двумя числами. Провайдеры карт принимают пару значений строкой, и лишнее разделение только добавляет работы шаблону.
Отдаём точки скриптом страницы:
$points = [];$res = CIBlockElement::GetList(['SORT' => 'ASC'], ['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y'], false, false, ['ID', 'NAME', 'PROPERTY_COORDS', 'PROPERTY_WORK_TIME']);while ($row = $res->GetNext()) { $points[] = ['id' => $row['ID'], 'name' => $row['NAME'], 'coords' => $row['PROPERTY_COORDS_VALUE'], 'time' => $row['PROPERTY_WORK_TIME_VALUE']];}echo '<script>window.shopPoints = ' . \Bitrix\Main\Web\Json::encode($points) . ';</script>';Выборка идёт один раз и кладёт готовый список в страницу. Запрос к серверу за каждой меткой отдельным вызовом - типовая ошибка, которая заметна уже на трёх десятках точек.
Связываем список адресов с картой:
document.querySelectorAll('[data-point]').forEach((node) => { node.addEventListener('click', () => { const point = window.shopPoints.find((p) => String(p.id) === node.dataset.point); if (point) { map.setCenter(point.coords.split(',').map(Number), 15); } });});// список остаётся обычной разметкой: он виден поиску и работает без скриптовСписок адресов делают обычной разметкой, а карту - дополнением к нему. Поисковые системы видят текст адресов, а посетитель без загруженной карты всё равно получает контакты.
Отбираем точки по городу:
// города - разделы инфоблока, тогда фильтр это выбор раздела$res = CIBlockElement::GetList([], ['IBLOCK_ID' => $iblockId, 'SECTION_CODE' => $cityCode, 'INCLUDE_SUBSECTIONS' => 'Y'], false, false, ['ID', 'NAME', 'PROPERTY_COORDS']);Города удобнее держать разделами инфоблока, а не строковым свойством. Разделы дают готовый адрес страницы города, фильтрацию без лишнего кода и понятную структуру для контент-менеджера.
Ключ доступа к сервису карт хранят в настройках, а не в шаблоне. Ключ в разметке уезжает в репозиторий и в чужие руки, а при смене ключа его приходится искать по всем шаблонам сайта.
Точки меняются редко, поэтому блок карты кэшируют надолго. Сброс делают по тегу при изменении элементов инфоблока, а не ожиданием истечения времени жизни кэша.
Типичные проблемы
Метки не появляются на карте, ошибок в консоли нет.
В координатах точки пустое значение или неверный разделитель. Проверяют свойство у элементов: одна точка с пустыми координатами обычно ломает весь набор.
Карта грузится долго, страница подтормаживает.
Скрипт карты подключается на всех страницах сайта. Его подключают только там, где карта действительно нужна.
Адреса не находятся поиском по сайту.
Список точек рисуется скриптом, а в разметке его нет. Текстовый список адресов оставляют в разметке рядом с картой.
После добавления магазина он не появился на сайте.
Блок карты отдаётся из кэша. Кэш сбрасывают по тегу при изменении элементов инфоблока точек.
Ключ доступа к картам перестал работать.
Он задан в шаблоне и попал в репозиторий или на другой домен. Ключ хранят в настройках модуля и ограничивают доменом.
Частые вопросы
Где хранить координаты точек?
В свойстве элемента инфоблока строкой из двух чисел. Отдельный справочник заводят, только если у точки много собственных данных и она нужна другим разделам сайта.
Нужен ли отдельный инфоблок под точки?
Да, это самый простой вариант: точки правит контент-менеджер, а разделы дают города. Складам магазина такой инфоблок не замена: они живут в модуле каталога.
Как связать точки со складами и пунктами выдачи?
Общим кодом или свойством-ссылкой на склад. Тогда карта показывает те же точки, что и оформление заказа, и данные не расходятся.
Что делать с закрытыми магазинами?
Снимать элемент с публикации или помечать признаком. Удаление теряет историю, а признак позволяет показать точку как временно не работающую.
Можно ли обойтись без внешнего сервиса карт?
Для нескольких точек хватит списка с адресами и ссылками на карты. Внешний сервис нужен там, где точек десятки и важен подбор ближайшей.
Смежное
- Шаблон сайта - оглавление подтемы
- Баннеры и слайдеры: инфоблок или модуль рекламы - соседний блок на странице
- Включаемые области: файлы, области шаблона, правка менеджером - контакты рядом с картой
- Самовывоз и пункты выдачи: склады, список на оформлении, заказ - те же точки в оформлении заказа
- Свойства инфоблока: чтение, запись и фильтрация по значению - хранение данных точки
- Кэш не срабатывает: страница собирается заново каждый раз - кэш блока с картой
- Шаблоны сайта - устройство шаблона целиком