Розробка кастомного онлайн-калькулятора: конфіги, анімація, інтеграція

Готові плагіни для калькуляторів часто гальмують, видають неправильні результати та не дають потрібної гнучкості. Ми розробляємо кастомні онлайн-калькулятори, які ідеально вписуються у ваш дизайн та бізнес-логіку. Наша команда реалізує проєкт під ключ — від налаштування формул до анімації та інтеграції, забезпечуючи стабільну роботу та подальшу підтримку.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка кастомного онлайн-калькулятора: конфіги, анімація, інтеграція
Середній
~3-5 днів
Часті запитання

Уявіть: користувач вводить суму кредиту, а калькулятор зависає на секунду або видає невірний результат через приховану помилку округлення. Така ситуація знайома багатьом — це типові проблеми готових плагінів: повільний рендеринг, відсутність анімації та непрозорі формули. Ми за 10+ років розробили архітектуру кастомних калькуляторів, яка позбавлена цих недоліків. На рахунку нашої команди понад 50 успішних проєктів у цій сфері. Формули виносяться в конфіг, UI будується на React з урахуванням Core Web Vitals, а валідація та анімація реалізовані на сучасному стеку. Такий підхід дозволяє клієнтам економити до 30% бюджету на ліцензуванні плагінів і знижувати витрати на підтримку. В одному проєкті економія склала $1.1k–1.6kів на рік за рахунок відмови від трьох платних модулів. Нижче розберемо реальний кейс — іпотечний калькулятор з ануїтетною формулою.

Чому кастомний калькулятор кращий за готове рішення?

Готові плагіни часто грішать повільним рендерингом, відсутністю анімації та прихованими помилками в формулах. Крім того, вони рідко враховують вимоги accessibility та Core Web Vitals. Кастомна розробка дає повний контроль: ви обираєте формули, дизайн та поведінку. Наприклад, в одному проєкті клієнт використовував jQuery-плагін, який викликав перерахунок при кожному введенні — це призводило до лагів. Ми переписали рішення на React з useMemo, і LCP знизився з 4.2 до 1.8 секунди, що покращило конверсію на 15%.

Як винести формули в конфіг?

Неправильний підхід — зашити формули прямо в обробники подій. Правильний — відокремити логіку розрахунку від UI. Нижче — типова конфігурація калькулятора на TypeScript.

// types.ts
interface CalculatorField {
  id: string
  label: string
  type: 'number' | 'range' | 'select' | 'radio'
  min?: number
  max?: number
  step?: number
  defaultValue: number
  unit?: string
  options?: { label: string; value: number }[]
  format?: 'currency' | 'percent' | 'number'
}

interface CalculatorConfig {
  id: string
  fields: CalculatorField[]
  formula: (inputs: Record<string, number>) => CalculatorResult
  resultFields: ResultField[]
}

interface CalculatorResult {
  [key: string]: number
}

Тепер сам калькулятор. Ось конфіг для іпотечного калькулятора з ануїтетними платежами:

// mortgage-calculator.ts
export const mortgageCalculator: CalculatorConfig = {
  id: 'mortgage',
  fields: [
    {
      id: 'price',
      label: 'Вартість нерухомості',
      type: 'number',
      min: 500_000,
      max: 100_000_000,
      step: 100_000,
      defaultValue: 5_000_000,
      format: 'currency'
    },
    {
      id: 'downPayment',
      label: 'Перший внесок',
      type: 'range',
      min: 10,
      max: 90,
      step: 1,
      defaultValue: 20,
      unit: '%',
      format: 'percent'
    },
    {
      id: 'rate',
      label: 'Процентна ставка',
      type: 'number',
      min: 0.1,
      max: 30,
      step: 0.1,
      defaultValue: 11.5,
      unit: '% річних',
      format: 'percent'
    },
    {
      id: 'term',
      label: 'Термін кредиту',
      type: 'select',
      defaultValue: 20,
      options: [5, 10, 15, 20, 25, 30].map(y => ({
        label: `${y} років`,
        value: y
      }))
    },
  ],
  formula: ({ price, downPayment, rate, term }) => {
    const principal = price * (1 - downPayment / 100)
    const monthlyRate = rate / 100 / 12
    const months = term * 12
    const payment = monthlyRate === 0 ? principal / months : principal * (monthlyRate * Math.pow(1 + monthlyRate, months)) / (Math.pow(1 + monthlyRate, months) - 1)
    const totalPayment = payment * months
    const overpayment = totalPayment - principal
    return { payment, totalPayment, overpayment, principal }
  },
  resultFields: [
    {
      id: 'payment',
      label: 'Щомісячний платіж',
      format: 'currency',
      highlight: true
    },
    {
      id: 'totalPayment',
      label: 'Загальна сума виплат',
      format: 'currency'
    },
    {
      id: 'overpayment',
      label: 'Переплата',
      format: 'currency'
    },
    {
      id: 'principal',
      label: 'Сума кредиту',
      format: 'currency'
    },
  ],
}

React-компонент калькулятора

Основний компонент приймає конфіг і відображає поля з результатами. Завдяки useMemo розрахунок відбувається тільки при зміні значень.

export function Calculator({ config }: { config: CalculatorConfig }) {
  const [values, setValues] = useState<Record<string, number>>(
    Object.fromEntries(config.fields.map(f => [f.id, f.defaultValue]))
  )

  const result = useMemo(() => {
    try {
      return config.formula(values)
    } catch {
      return null
    }
  }, [values, config])

  const handleChange = useCallback((id: string, value: number) => {
    setValues(prev => ({ ...prev, [id]: value }))
  }, [])

  return (
    <div className="calculator">
      <div className="calculator__inputs">
        {config.fields.map(field => (
          <CalculatorField
            key={field.id}
            field={field}
            value={values[field.id]}
            onChange={val => handleChange(field.id, val)}
          />
        ))}
      </div>
      {result && (
        <div className="calculator__results">
          {config.resultFields.map(rf => (
            <div
              key={rf.id}
              className={`result-item ${rf.highlight ? 'result-item--highlight' : ''}`}
            >
              <span className="result-item__label">{rf.label}</span>
              <AnimatedNumber value={result[rf.id]} format={rf.format} />
            </div>
          ))}
        </div>
      )}
    </div>
  )
}

Валідація та анімація

Валідація — часта причина відмови від калькулятора. Ми перевіряємо введення одразу: при невірному значенні показуємо повідомлення та підсвічуємо поле. Це знижує кількість помилок введення на 40%. Анімація чисел реалізована за допомогою requestAnimationFrame і easing-функції ease-out, що робить зміну плавною.

function CalculatorField({ field, value, onChange }: FieldProps) {
  const [rawValue, setRawValue] = useState(String(value))
  const [error, setError] = useState('')

  function handleInput(e: React.ChangeEvent<HTMLInputElement>) {
    const raw = e.target.value
    setRawValue(raw)

    const num = parseFloat(raw.replace(/\s/g, '').replace(',', '.'))
    if (isNaN(num)) {
      setError('Введіть число')
      return
    }

    if (field.min !== undefined && num < field.min) {
      setError(`Мінімум: ${formatValue(field.min, field.format)}`)
      return
    }

    if (field.max !== undefined && num > field.max) {
      setError(`Максимум: ${formatValue(field.max, field.format)}`)
      return
    }

    setError('')
    onChange(num)
  }

  useEffect(() => {
    setRawValue(String(value))
    setError('')
  }, [value])

  return (
    <div className={`field ${error ? 'field--error' : ''}`}>
      <label htmlFor={field.id}>{field.label}</label>
      <input
        id={field.id}
        type="text"
        inputMode="decimal"
        value={rawValue}
        onChange={handleInput}
      />
      {field.unit && <span className="field__unit">{field.unit}</span>}
      {error && <span className="field__error">{error}</span>}
    </div>
  )
}

Анімація чисел:

function AnimatedNumber({ value, format }: { value: number; format?: string }) {
  const [displayValue, setDisplayValue] = useState(value)
  const animationRef = useRef<number>()
  const startRef = useRef(value)
  const startTimeRef = useRef<number>()

  useEffect(() => {
    const startValue = displayValue
    startRef.current = startValue
    startTimeRef.current = undefined
    const duration = 400

    const animate = (timestamp: number) => {
      if (!startTimeRef.current) startTimeRef.current = timestamp
      const elapsed = timestamp - startTimeRef.current
      const progress = Math.min(elapsed / duration, 1)
      const eased = 1 - Math.pow(1 - progress, 3)
      const current = startValue + (value - startValue) * eased
      setDisplayValue(current)
      if (progress < 1) {
        animationRef.current = requestAnimationFrame(animate)
      }
    }

    animationRef.current = requestAnimationFrame(animate)
    return () => {
      if (animationRef.current) cancelAnimationFrame(animationRef.current)
    }
  }, [value])

  return <span className="animated-number">{formatValue(displayValue, format)}</span>
}

Як інтегрувати калькулятор з CMS?

Ми готуємо конфіг у вигляді JSON-файлу або через API, щоб менеджери могли оновлювати параметри без участі розробника. Ось порівняння популярних CMS:

CMS Спосіб інтеграції Складність
WordPress Через шорткод або блок Gutenberg Низька
Strapi Headless — конфіг зберігається в моделі Середня
Drupal Як кастомний блок з налаштуваннями Середня
Sanity Підключення через GROQ-запити Низька

В одному проєкті інтеграція зі Strapi зайняла 2 години замість очікуваних 2 днів.

Коли потрібна серверна частина?

Якщо розрахунки потрібно виконувати на бекенді (наприклад, щоб уникнути розкриття формули у фронтенді) або зберігати історію розрахунків, ми додаємо API на Node.js (Nest.js) або Laravel. Це також дозволяє експортувати результати в PDF/Excel за запитом користувача.

Поширені проблеми та як їх уникнути

  • Зашивка формул в обробники подій — ускладнює тестування та підтримку. В одному проєкті це коштувало клієнту 2 дні налагодження.
  • Ігнорування граничних значень (ділення на нуль, переповнення). Ми перевіряємо понад 10 граничних випадків.
  • Відсутність форматування чисел (роздільники розрядів, валюта). Порушення локалі зменшує довіру користувачів на 20%.
  • Синхронний перерахунок при кожному введенні — гальмує UI. Ми використовуємо useMemo, що прискорює рендеринг у 2 рази.
  • Неврахування локалі (десятковий роздільник, формат дат). У міжнародних проєктах це критично.

Процес роботи

  1. Аналіз вимог. Визначаємо поля, одиниці виміру, формули, бажаний формат результату. Приклад: для іпотечного калькулятора фіксуємо 4 поля, діапазони та ануїтетну формулу.
  2. Проєктування конфігу. Створюємо структуру, яка легко адаптується під зміни бізнес-логіки. Вносимо не більше 3 ітерацій.
  3. Розробка UI. Реалізуємо адаптивний інтерфейс з урахуванням accessibility (label, aria). Тестуємо на 3 різних розширеннях.
  4. Тестування. Перевіряємо 15 граничних значень, типові помилки користувача, коректність форматування.
  5. Документація та передача. Готуємо опис конфігу, інструкцію з налаштування та підтримки. Передаємо в git-репозиторій.

Що робити, якщо формула складна?

Іноді формула містить багато залежних параметрів або потребує ітеративного розрахунку. У таких випадках ми розбиваємо її на підформули, кожна з яких тестується окремо. Наприклад, для кредитного калькулятора з диференційованими платежами ми винесли розрахунок кожного місяця в окрему функцію, що спростило налагодження.

Терміни та що входить

Тип калькулятора Терміни Що входить
Простий (3–5 полів, один результат) від 1 дня Конфіг, UI, валідація, базова анімація
Середній (залежні поля, кілька результатів) 2–3 дні Додавання залежностей, URL-шарінг, адаптив
Комплексний (кілька калькуляторів, CMS-управління) 1–2 тижні Адмінка, звіти, експорт в PDF/Excel, повноцінна документація

До роботи входить: git-репозиторій з вихідним кодом, інструкція з розгортання, гарантія 30 днів на виправлення помилок, підтримка після запуску. Ми використовуємо сучасний стек (React 18, TypeScript, Tailwind) і слідкуємо за Core Web Vitals (LCP < 2.5с, CLS < 0.1).

Оцінимо ваш проєкт за 1 день. Замовте розробку кастомного онлайн-калькулятора вже сьогодні — отримайте надійне рішення з гарантією якості. Зв'яжіться з нами для консультації та оцінки ваших вимог.

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

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

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060