Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies и даете Согласие на обработку Ваших персональных данных в соответствии с Политика в отношении обработки персональных данных
Ок
 

Расчет стоимости

Заполните форму ниже и наш логист в течение 5 минут перезвонит Вам для уточнения стоимости рейса и других вопросов (если нужно)
Куда лучше Вам ответить
Нажимая на кнопку "отправить", вы даете согласие на обработку персональных данных и соглашаетесь c политикой конфиденциальности
Расчет стоимости

Калькулятор грузоперевозок

Укажите точки загрузки и выгрузки — маршрут построится автоматически по Яндекс Картам.

Маршрут перевозки
Введите точки маршрута и нажмите «Построить маршрут».
Параметры перевозки
.apcalc { --ap-bg: #f6f1e8; --ap-surface: rgba(255, 255, 255, 0.86); --ap-surface-strong: #ffffff; --ap-text: #1f1d1a; --ap-muted: #6f685f; --ap-line: #e4d9c9; --ap-accent: #b4874d; --ap-accent-dark: #946a37; --ap-accent-soft: #f4eadc; --ap-info: #eef4ff; --ap-info-text: #2a5ab8; --ap-success: #edf9f0; --ap-success-text: #17804b; --ap-error: #fff1f2; --ap-error-text: #b2263b; --ap-shadow: 0 18px 44px rgba(31, 29, 26, 0.08); --ap-radius-xl: 22px; --ap-radius-lg: 18px; --ap-radius-md: 14px; --ap-radius-sm: 12px; --ap-transition: 0.2s ease; padding: 24px 0; } .apcalc, .apcalc * { box-sizing: border-box; } .apcalc__inner { max-width: 1120px; margin: 0 auto; padding: 34px 24px; border-radius: var(--ap-radius-xl); background: radial-gradient(circle at top right, rgba(180, 135, 77, 0.08), transparent 25%), linear-gradient(135deg, #faf7f2 0%, var(--ap-bg) 100%); box-shadow: var(--ap-shadow); font-family: inherit; color: var(--ap-text); } .apcalc__head { margin-bottom: 24px; } .apcalc__eyebrow { margin-bottom: 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ap-accent-dark); } .apcalc__title { margin: 0 0 8px; font-size: 34px; line-height: 1.15; font-weight: 800; color: var(--ap-text); } .apcalc__subtitle { max-width: 720px; margin: 0; font-size: 15px; line-height: 1.6; color: var(--ap-muted); } .apcalc__form { display: flex; flex-direction: column; gap: 18px; } .apcalc__card { padding: 22px; border: 1px solid var(--ap-line); border-radius: var(--ap-radius-lg); background: var(--ap-surface); backdrop-filter: blur(6px); } .apcalc__card-title { margin-bottom: 16px; font-size: 18px; font-weight: 700; color: var(--ap-text); } .apcalc__grid { display: grid; gap: 14px; } .apcalc__grid--route { grid-template-columns: repeat(3, minmax(0, 1fr)); } .apcalc__grid--params { grid-template-columns: repeat(3, minmax(0, 1fr)); } .apcalc__field { display: flex; flex-direction: column; } .apcalc__field--wide { grid-column: span 3; } .apcalc__field label { margin-bottom: 7px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: #504a42; } .apcalc__field input, .apcalc__field select { height: 50px; width: 100%; padding: 0 14px; border: 1.5px solid var(--ap-line); border-radius: var(--ap-radius-sm); background: var(--ap-surface-strong); font-size: 15px; color: var(--ap-text); transition: border-color var(--ap-transition), box-shadow var(--ap-transition), background var(--ap-transition); } .apcalc__field input::placeholder { color: #9a9186; } .apcalc__field input:focus, .apcalc__field select:focus { outline: none; border-color: var(--ap-accent); box-shadow: 0 0 0 4px rgba(180, 135, 77, 0.14); } .apcalc__field input[readonly] { background: #fbfaf7; color: #5d564d; } .apcalc__hint { margin-top: 8px; font-size: 13px; line-height: 1.45; color: var(--ap-muted); } .apcalc__routebar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 16px; margin-bottom: 16px; } .apcalc__ghost-btn { height: 46px; padding: 0 18px; border: 1.5px solid var(--ap-accent); border-radius: var(--ap-radius-sm); background: transparent; color: var(--ap-accent-dark); font-size: 14px; font-weight: 700; cursor: pointer; transition: all var(--ap-transition); } .apcalc__ghost-btn:hover { background: var(--ap-accent-soft); border-color: var(--ap-accent-dark); } .apcalc__status { display: inline-flex; align-items: center; min-height: 46px; padding: 10px 14px; border-radius: var(--ap-radius-sm); font-size: 14px; font-weight: 600; } .apcalc__status--info { background: var(--ap-info); color: var(--ap-info-text); } .apcalc__status--loading { background: #fff7e8; color: #c68216; } .apcalc__status--success { background: var(--ap-success); color: var(--ap-success-text); } .apcalc__status--error { background: var(--ap-error); color: var(--ap-error-text); } .apcalc__map { width: 100%; height: 370px; border: 1px solid var(--ap-line); border-radius: 18px; overflow: hidden; background: #e7ddd0; } .apcalc__checks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 18px; } .apcalc__check { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 12px 14px; border: 1.5px solid var(--ap-line); border-radius: var(--ap-radius-sm); background: var(--ap-surface-strong); cursor: pointer; transition: border-color var(--ap-transition), background var(--ap-transition); font-size: 14px; font-weight: 600; color: #453f38; } .apcalc__check:hover { border-color: #d1bc9d; background: #fffdf9; } .apcalc__check input { width: 18px; height: 18px; accent-color: var(--ap-accent); flex: 0 0 auto; } .apcalc__main-btn { height: 56px; border: none; border-radius: 14px; background: linear-gradient(135deg, var(--ap-accent) 0%, var(--ap-accent-dark) 100%); color: #fff; font-size: 16px; font-weight: 800; letter-spacing: 0.01em; cursor: pointer; box-shadow: 0 12px 24px rgba(148, 106, 55, 0.24); transition: transform var(--ap-transition), box-shadow var(--ap-transition), opacity var(--ap-transition); } .apcalc__main-btn:hover { transform: translateY(-1px); box-shadow: 0 14px 26px rgba(148, 106, 55, 0.3); } .apcalc__result { display: none; margin-top: 22px; padding: 24px; border: 1px solid var(--ap-line); border-radius: var(--ap-radius-lg); background: #fff; } .apcalc__result.is-visible { display: block; } .apcalc__result.is-error { border-color: #f1c1c8; background: #fff7f8; color: var(--ap-error-text); } .apcalc__result-top { margin-bottom: 12px; } .apcalc__result-tag { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: #7f776d; } .apcalc__result-route { margin-top: 5px; font-size: 20px; line-height: 1.35; font-weight: 700; color: var(--ap-text); } .apcalc__result-meta { margin-top: 8px; font-size: 14px; color: var(--ap-muted); } .apcalc__result-price { margin: 18px 0 16px; font-size: 44px; line-height: 1; font-weight: 800; color: var(--ap-accent-dark); } .apcalc__result-list { margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.85; color: #4f4a43; } .apcalc__result-note { margin-top: 16px; padding: 12px 14px; border-radius: 12px; background: #fbf6ee; font-size: 13px; line-height: 1.55; color: var(--ap-muted); } @media (max-width: 980px) { .apcalc__grid--route, .apcalc__grid--params { grid-template-columns: 1fr; } .apcalc__field--wide { grid-column: span 1; } .apcalc__checks { grid-template-columns: 1fr; } } @media (max-width: 768px) { .apcalc__inner { padding: 20px 14px; } .apcalc__title { font-size: 26px; } .apcalc__map { height: 290px; } .apcalc__result-price { font-size: 34px; } }(function () { "use strict"; const YANDEX_API_KEY = f0576e4c-a2f5-4574-9921-44c19657539e; const VEHICLES = { gazelle: { name: "Газель 1.5 т", rate: 32, minPrice: 9000, maxWeight: 1.5, maxVolume: 9, loading: 1000, unloading: 1000 }, truck3: { name: "3-тонник", rate: 40, minPrice: 13000, maxWeight: 3, maxVolume: 18, loading: 1400, unloading: 1400 }, truck5: { name: "5-тонник", rate: 48, minPrice: 17000, maxWeight: 5, maxVolume: 36, loading: 1800, unloading: 1800 }, truck10: { name: "10-тонник", rate: 58, minPrice: 24000, maxWeight: 10, maxVolume: 45, loading: 2200, unloading: 2200 }, truck20: { name: "Фура 20 т", rate: 68, minPrice: 32000, maxWeight: 20, maxVolume: 82, loading: 2800, unloading: 2800 }, reefer20: { name: "Рефрижератор 20 т", rate: 85, minPrice: 42000, maxWeight: 20, maxVolume: 82, loading: 3200, unloading: 3200 } }; const dom = { form: document.getElementById("apcalcForm"), from: document.getElementById("apFrom"), to: document.getElementById("apTo"), buildRoute: document.getElementById("apBuildRoute"), routeStatus: document.getElementById("apRouteStatus"), distance: document.getElementById("apDistance"), time: document.getElementById("apTime"), manualDistance: document.getElementById("apManualDistance"), map: document.getElementById("apMap"), vehicle: document.getElementById("apVehicle"), vehicleHint: document.getElementById("apVehicleHint"), weight: document.getElementById("apWeight"), volume: document.getElementById("apVolume"), loading: document.getElementById("apLoading"), unloading: document.getElementById("apUnloading"), urgent: document.getElementById("apUrgent"), insurance: document.getElementById("apInsurance"), result: document.getElementById("apResult") }; const state = { map: null, route: null, ymapsReady: false, routeDistanceKm: 0, routeDurationMin: 0, routeRequestId: 0, inputTimer: null }; function escapeHtml(value) { return String(value) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function money(value) { return new Intl.NumberFormat("ru-RU", { style: "currency", currency: "RUB", maximumFractionDigits: 0 }).format(value); } function durationText(totalMinutes) { const h = Math.floor(totalMinutes / 60); const m = totalMinutes % 60; if (h > 0 && m > 0) return h + " ч " + m + " мин"; if (h > 0) return h + " ч"; return m + " мин"; } function setStatus(text, type) { dom.routeStatus.className = "apcalc__status apcalc__status--" + type; dom.routeStatus.textContent = text; } function clearRouteInfo() { state.routeDistanceKm = 0; state.routeDurationMin = 0; dom.distance.value = ""; dom.time.value = ""; } function getVehicle() { return VEHICLES[dom.vehicle.value]; } function updateVehicleHint() { const v = getVehicle(); dom.vehicleHint.textContent = "Грузоподъемность: " + v.maxWeight + " т • Объем: " + v.maxVolume + " м³ • Минимальный заказ: " + money(v.minPrice); } function getEffectiveDistance() { const manual = Number(dom.manualDistance.value); if (manual > 0) return manual; return state.routeDistanceKm; } function loadYandexMaps() { return new Promise(function (resolve, reject) { if (window.ymaps) { window.ymaps.ready(resolve); return; } const script = document.createElement("script"); script.src = "https://api-maps.yandex.ru/2.1/?apikey=" + encodeURIComponent(YANDEX_API_KEY) + "&lang=ru_RU"; script.async = true; script.onload = function () { if (!window.ymaps) { reject(new Error("ymaps not found")); return; } window.ymaps.ready(resolve); }; script.onerror = function () { reject(new Error("maps load error")); }; document.head.appendChild(script); }); } function initMap() { state.map = new window.ymaps.Map("apMap", { center: [59.9386, 30.3141], zoom: 9, controls: ["zoomControl", "fullscreenControl"] }); state.ymapsReady = true; setStatus("Карта загружена. Можно строить маршрут.", "success"); } function removeRoute() { if (state.map && state.route) { state.map.geoObjects.remove(state.route); state.route = null; } } async function buildRoute() { const from = dom.from.value.trim(); const to = dom.to.value.trim(); if (!from || !to) { clearRouteInfo(); removeRoute(); setStatus("Укажите точки загрузки и выгрузки.", "error"); return; } if (!state.ymapsReady || !window.ymaps) { setStatus("Яндекс Карты еще загружаются.", "loading"); return; } const currentRequestId = ++state.routeRequestId; setStatus("Строим маршрут...", "loading"); try { const route = await window.ymaps.route([from, to], { routingMode: "auto", mapStateAutoApply: false }); if (currentRequestId !== state.routeRequestId) return; removeRoute(); state.route = route; state.map.geoObjects.add(route); const bounds = route.getBounds(); if (bounds) { state.map.setBounds(bounds, { checkZoomRange: true, zoomMargin: 30 }); } state.routeDistanceKm = Math.max(1, Math.round(route.getLength() / 1000)); state.routeDurationMin = Math.max(1, Math.round(route.getTime() / 60)); dom.distance.value = state.routeDistanceKm.toLocaleString("ru-RU") + " км"; dom.time.value = durationText(state.routeDurationMin); setStatus( "Маршрут построен: " + state.routeDistanceKm.toLocaleString("ru-RU") + " км", "success" ); } catch (error) { if (currentRequestId !== state.routeRequestId) return; clearRouteInfo(); removeRoute(); setStatus( "Не удалось построить маршрут. Проверьте адреса или используйте расстояние вручную.", "error" ); } } function debounceBuildRoute() { clearTimeout(state.inputTimer); clearRouteInfo(); if (!dom.from.value.trim() || !dom.to.value.trim()) { removeRoute(); setStatus("Введите точки маршрута.", "info"); return; } state.inputTimer = setTimeout(function () { buildRoute(); }, 900); } function showError(message) { dom.result.className = "apcalc__result is-visible is-error"; dom.result.innerHTML = "" + escapeHtml(message) + ""; } function showResult(html) { dom.result.className = "apcalc__result is-visible"; dom.result.innerHTML = html; } function calculate(event) { event.preventDefault(); const from = dom.from.value.trim(); const to = dom.to.value.trim(); const distanceKm = getEffectiveDistance(); const weight = Number(dom.weight.value); const volume = Number(dom.volume.value); const vehicle = getVehicle(); if (!from || !to) { showError("Укажите точки загрузки и выгрузки."); return; } if (!distanceKm || distanceKm <= 0) { showError("Сначала постройте маршрут или укажите расстояние вручную."); return; } if (!weight || weight <= 0) { showError("Укажите корректный вес груза."); return; } if (!volume || volume <= 0) { showError("Укажите корректный объем груза."); return; } if (weight > vehicle.maxWeight) { showError( "Вес груза превышает грузоподъемность выбранного транспорта (" + vehicle.maxWeight + " т)." ); return; } if (volume > vehicle.maxVolume) { showError( "Объем груза превышает допустимый объем выбранного транспорта (" + vehicle.maxVolume + " м³)." ); return; } const basePrice = Math.max(distanceKm * vehicle.rate, vehicle.minPrice); let total = basePrice; const breakdown = []; breakdown.push( "Базовый тариф: " + money(basePrice) + " (" + distanceKm + " км × " + vehicle.rate + " ₽/км)" ); breakdown.push( "Транспорт: " + vehicle.name + " • " + vehicle.maxWeight + " т / " + vehicle.maxVolume + " м³" ); breakdown.push("Вес груза: " + weight + " т"); breakdown.push("Объем груза: " + volume + " м³"); if (dom.loading.checked) { total += vehicle.loading; breakdown.push("Погрузка: " + money(vehicle.loading)); } if (dom.unloading.checked) { total += vehicle.unloading; breakdown.push("Разгрузка: " + money(vehicle.unloading)); } if (dom.insurance.checked) { const insurancePrice = Math.round(basePrice * 0.01); total += insurancePrice; breakdown.push("Страхование: " + money(insurancePrice)); } if (dom.urgent.checked) { const urgentPrice = Math.round(total * 0.2); total += urgentPrice; breakdown.push("Срочная доставка: " + money(urgentPrice)); } const usingManualDistance = Number(dom.manualDistance.value) > 0; const html = '
' + '
Маршрут
' + '
' + escapeHtml(from) + " → " + escapeHtml(to) + "
" + '
' + "Расстояние: " + distanceKm.toLocaleString("ru-RU") + " км" + (state.routeDurationMin && !usingManualDistance ? " • Время в пути: " + escapeHtml(durationText(state.routeDurationMin)) : "") + (usingManualDistance ? " • Использовано расстояние, введенное вручную" : "") + "
" + "
" + '
' + money(total) + "
" + '
    ' + breakdown.map(function (item) { return "
  • " + escapeHtml(item) + "
  • "; }).join("") + "
" + '
' + "Это ориентировочная стоимость. Для точного коммерческого предложения рекомендуем подтвердить детали маршрута, характер груза и условия погрузки/выгрузки." + "
"; showResult(html); } function bindEvents() { dom.buildRoute.addEventListener("click", buildRoute); dom.from.addEventListener("input", debounceBuildRoute); dom.to.addEventListener("input", debounceBuildRoute); dom.vehicle.addEventListener("change", updateVehicleHint); dom.form.addEventListener("submit", calculate); updateVehicleHint(); } async function start() { bindEvents(); if (!YANDEX_API_KEY || YANDEX_API_KEY === "ВАШ_API_КЛЮЧ_ЯНДЕКС") { setStatus("Укажите API-ключ Яндекс Карт в JS-коде.", "error"); return; } try { setStatus("Загружаем Яндекс Карты...", "loading"); await loadYandexMaps(); initMap(); } catch (error) { setStatus( "Не удалось загрузить Яндекс Карты. Проверьте API-ключ и настройки доступа.", "error" ); } } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", start); } else { start(); } })();
Made on
Tilda