Разработка виджета выбора ПВЗ на карте на Vue.js для 1С-Битрикс
Выбор пункта выдачи заказа на карте — один из самых конверсионно значимых элементов checkout. Пользователь должен видеть ближайшие ПВЗ, выбрать удобный и получить корректную стоимость доставки. Реализация требует интеграции карт (Яндекс или Leaflet), API службы доставки и Битрикс-модуля sale.
Источники данных ПВЗ
Координаты и атрибуты ПВЗ приходят из API службы доставки:
-
СДЭК:
https://api.cdek.ru/v2/deliverypoints— список точек с координатами, режимом работы, типом -
Boxberry:
https://api.boxberry.ru/json.php?token=...&method=ListPoints -
Почта России: API
otpravka.pochta.ru— список ОПС - DPD, Ozon Rocket, Яндекс.Доставка — собственные API
Все эти данные кэшируются на сервере (в b_cached_files или Redis), не запрашиваются напрямую с клиента — это скрывает API-ключи и ускоряет ответ.
Архитектура виджета
PvzMapWidget.vue
├── MapContainer.vue — Яндекс.Карты или Leaflet
├── PvzList.vue — список ПВЗ рядом с картой (мобильный вид)
├── PvzMarker.vue — кастомная метка с иконкой службы
├── PvzPopup.vue — попап с деталями (адрес, часы, стоимость)
└── DeliveryCostBadge.vue — стоимость доставки в данный ПВЗ
Интеграция с Яндекс.Картами
// После загрузки ymaps
const map = new ymaps.Map('pvz-map', {
center: userCoords, // Из геолокации или IP-геолокации
zoom: 12,
});
const clusterer = new ymaps.Clusterer({ preset: 'islands#greenClusterIcons' });
pvzPoints.forEach(pvz => {
const placemark = new ymaps.Placemark(
[pvz.latitude, pvz.longitude],
{ balloonContent: pvz.address },
{ preset: 'islands#greenDotIcon' }
);
placemark.events.add('click', () => selectPvz(pvz));
clusterer.add(placemark);
});
map.geoObjects.add(clusterer);
Vue управляет состоянием (выбранный ПВЗ, фильтры по службам), карта — через ref и прямое API.
Определение местоположения пользователя
Три источника, используются последовательно:
-
Браузерная геолокация (
navigator.geolocation.getCurrentPosition) — самый точный, требует разрешения -
IP-геолокация — через Битрикс (
\Bitrix\Sale\Location\LocationManager::getUserLocation()) или внешний сервис - Последний выбор — из localStorage/cookie
Интеграция с checkout
При выборе ПВЗ — обновляем store:
function selectPvz(pvz) {
checkoutStore.setDeliveryPoint({
deliveryId: pvz.deliveryServiceId,
pvzCode: pvz.code,
address: pvz.address,
coords: [pvz.latitude, pvz.longitude],
});
// Пересчёт стоимости доставки
checkoutStore.recalculateDelivery();
}
Битрикс-доставка: \Bitrix\Sale\Delivery\Services\Manager::calculateDeliveryPrice() с передачей кода ПВЗ в поле доп. данных доставки.
Случай из практики
Маркетплейс с несколькими службами доставки одновременно (СДЭК + Boxberry + Почта России). На карте — три слоя меток с переключением. Пользователь видит все ПВЗ одновременно или фильтрует по службе. Главная сложность: СДЭК отдаёт 20 000+ точек по России — загружать все при открытии нельзя. Решение: загрузка точек только в видимой области карты (map.getBounds()) при каждом изменении области просмотра (событие boundschange), с дебаунсом 500 мс. Кэш точек в Pinia — не перезапрашиваем уже загруженные области.
Сроки выполнения
| Вариант | Срок |
|---|---|
| ПВЗ одной службы доставки, Яндекс.Карты | от 5 до 8 рабочих дней |
| Несколько служб с фильтрацией | от 8 до 12 рабочих дней |
| С геолокацией, кластеризацией и lazy-загрузкой | от 12 до 18 рабочих дней |







