Разработка store locator (карта магазинов/офисов) на 1С-Битрикс
Пользователь вводит свой город или адрес и хочет увидеть ближайший магазин с маршрутом. Стандартными средствами Битрикс это не реализуется — нужна карта, геолокация, поиск по радиусу и фильтрация по типу точки. Всё это — кастомная разработка на базе инфоблока и картографического API.
Хранение данных о точках продаж
Каждая точка продаж — элемент инфоблока. Минимальный набор свойств:
-
ADDRESS— полный адрес (строка) -
LAT/LNG— координаты (числовые свойства с точностью до 6 знаков) -
PHONE— телефон (строка или множественное свойство) -
WORKING_HOURS— режим работы (строка или JSON:{"mon-fri": "9:00-20:00", "sat": "10:00-18:00"}) -
POINT_TYPE— тип точки (список: «Магазин», «Пункт выдачи», «Сервисный центр») -
CITY_ID— привязка к справочнику городов (элемент инфоблока городов) -
METRO— ближайшая станция метро -
PHOTO— фото точки
Координаты (LAT/LNG) — ключевые. Их нужно получить при создании точки: либо вручную через Яндекс.Карты, либо через геокодирование по адресу через API Яндекс.Геокодера при сохранении элемента:
AddEventHandler('iblock', 'OnBeforeIBlockElementAdd', 'geocodeStoreAddress');
function geocodeStoreAddress(&$arFields) {
if ($arFields['IBLOCK_ID'] !== IBLOCK_STORES_ID) return;
$address = urlencode($arFields['PROPERTIES']['ADDRESS']['VALUE']);
$http = new \Bitrix\Main\Web\HttpClient();
$response = $http->get("https://geocode-maps.yandex.ru/1.x/?apikey=KEY&format=json&geocode=$address");
$data = json_decode($response, true);
$coords = $data['response']['GeoObjectCollection']['featureMember'][0]['GeoObject']['Point']['pos'];
[$lng, $lat] = explode(' ', $coords);
$arFields['PROPERTIES']['LAT']['VALUE'] = $lat;
$arFields['PROPERTIES']['LNG']['VALUE'] = $lng;
}
Выбор картографического API
Яндекс.Карты API — приоритет для российской аудитории. Детальное покрытие РФ, пробки, геолокация пользователя, построение маршрутов. Тарифы: бесплатно до 1 000 запросов/сутки, далее коммерческий план.
2GIS API — хорошая альтернатива для городов РФ и СНГ, детальные карты офисных зданий (поэтажные планы).
OpenStreetMap + Leaflet.js — бесплатный вариант без лимитов на показы. Геокодирование через Nominatim (бесплатно, но с ограничениями по частоте запросов) или через платный Geocoding API.
Архитектура компонента
Компонент store locator состоит из двух частей:
PHP-бэкенд (component.php) — получает список точек из инфоблока, опционально фильтрует по городу или радиусу:
// Поиск в радиусе через формулу гаверсинуса (приближение)
// Для каталогов до 1000 точек — достаточно фильтрации на стороне JS
$res = CIBlockElement::GetList(
[],
['IBLOCK_ID' => IBLOCK_STORES_ID, 'ACTIVE' => 'Y'],
false, false,
['ID', 'NAME', 'PROPERTY_LAT', 'PROPERTY_LNG', 'PROPERTY_ADDRESS',
'PROPERTY_PHONE', 'PROPERTY_WORKING_HOURS', 'PROPERTY_POINT_TYPE']
);
$points = [];
while ($el = $res->GetNext()) {
$points[] = [
'id' => $el['ID'],
'name' => $el['NAME'],
'lat' => (float)$el['PROPERTY_LAT_VALUE'],
'lng' => (float)$el['PROPERTY_LNG_VALUE'],
'address' => $el['PROPERTY_ADDRESS_VALUE'],
'phone' => $el['PROPERTY_PHONE_VALUE'],
'hours' => $el['PROPERTY_WORKING_HOURS_VALUE'],
'type' => $el['PROPERTY_POINT_TYPE_VALUE'],
];
}
Данные прокидываются в JS через <script> с JSON или через AJAX-endpoint.
JS-фронтенд — инициализирует карту, добавляет маркеры, реализует поиск и фильтрацию:
// Яндекс.Карты API 3.0
import { load } from '@2gis/mapgl';
// или ymaps3.ready.then(() => { ... })
const map = new ymaps3.YMap(document.getElementById('map'), {
location: { center: [37.617, 55.755], zoom: 10 }
});
// Кластеризация для большого числа точек
const clusterer = new ymaps3.YMapClusterer({ ... });
Кластеризация маркеров — обязательна при 50+ точках. Без неё карта перегружена маркерами и неиспользуема. Яндекс.Карты 3.0 и Leaflet.js (через плагин Leaflet.markercluster) поддерживают это из коробки.
Поиск по геолокации пользователя
// Получение геопозиции браузера
navigator.geolocation.getCurrentPosition((pos) => {
const userLat = pos.coords.latitude;
const userLng = pos.coords.longitude;
// сортировка точек по расстоянию (формула гаверсинуса на JS)
stores.sort((a, b) => distance(userLat, userLng, a.lat, a.lng) - distance(userLat, userLng, b.lat, b.lng));
renderStoreList(stores.slice(0, 5)); // показываем 5 ближайших
});
При отказе пользователя от геолокации — фолбек: определение города по IP через Sypex Geo (PHP-библиотека, базы данных хранятся локально) или через API ip-api.com.
Боковая панель со списком точек
Карта без боковой панели — неудобный UX. Типичная компоновка: слева список точек с расстоянием от пользователя, справа карта. Клик по точке в списке центрирует карту и открывает балун. Клик по маркеру — подсвечивает карточку в списке.
Синхронизация реализуется через общий state (простой JS-объект или небольшая store на Vue/Alpine.js):
let selectedStore = null;
function selectStore(id) {
selectedStore = id;
// обновить подсветку в списке
document.querySelectorAll('.store-card').forEach(el => el.classList.remove('active'));
document.querySelector(`[data-store-id="${id}"]`).classList.add('active');
// переместить карту
map.setCenter([stores[id].lng, stores[id].lat], { duration: 300 });
}
Фильтрация по типу точки и городу
Выпадающий список с городами — это SELECT с onChange, который фильтрует массив stores на клиенте и перерисовывает маркеры. При 100+ городах список громоздкий; лучше — поле автодополнения с поиском по вводу.
Фильтр по типу точки (магазин / пункт выдачи / сервис) — чекбоксы, которые скрывают/показывают соответствующие маркеры через marker.setVisible(false).
Производительность при большом числе точек
При 500+ точках передача всего массива в JS при загрузке страницы нежелательна — большой JSON тормозит парсинг. Решение:
- Пагинированный AJAX-запрос: при старте загружаем точки в границах видимой области карты, при перемещении карты — подгружаем новые
-
Серверный поиск по радиусу: запрос к PHP с параметрами
lat,lng,radius, фильтрация в SQL через формулу гаверсинуса или через PostGIS (если PostgreSQL) -
Кеширование: список точек редко меняется, агрессивный кеш на 1 час в таблице
b_cache
Сроки
| Масштаб | Что входит | Срок |
|---|---|---|
| До 50 точек | Карта + список + фильтр по городу | 1–2 недели |
| 50–300 точек | + кластеры, геолокация, поиск рядом | 2–4 недели |
| 300+ точек | + серверный поиск по радиусу, PostGIS | 4–6 недель |
Store locator — точка контакта между онлайн и офлайн. Правильно реализованный, он снижает звонки в колл-центр с вопросом «а где вы находитесь» и повышает конверсию в посещение торговой точки.







