Розробка store locator (карти магазинів/офісів) на 1С-Bitrix
Користувач вводить своє місто або адресу й хоче побачити найближчий магазин з маршрутом. Стандартні засоби Bitrix — ні bitrix:catalog.element, ні торгові пропозиції — не вирішують це завдання. Потрібна карта, геолокація, пошук за радіусом і фільтрація за типом точки. Усе це — користувацька розробка на базі інфоблока та картографічного 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. Типова компоновка: зліва список точок із відстанню від користувача, справа карта. Клік по точці в списку центрує карту й відкриває балун. Клік по маркеру — підсвічує карточку в списку.
Синхронізація через загальний стан (простий 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 — точка контакту між онлайном й офлайном. Правильно реалізований, він зменшує дзвінки в колл-центр з питанням «а де ви знаходитесь» й підвищує конверсію в відвідування торговельної точки.







