Розробка store locator (карта магазинів/офісів) на 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Розробка store locator (карта магазинів/офісів) на 1С-Бітрікс
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Розробка 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 — точка контакту між онлайном й офлайном. Правильно реалізований, він зменшує дзвінки в колл-центр з питанням «а де ви знаходитесь» й підвищує конверсію в відвідування торговельної точки.