Вступ до Rive: інтерактивні анімації з State Machine
Ви запускаєте лендинг з анімацією завантаження, яка має реагувати на прогрес. Lottie не підходить — потрібно змінювати стан у відповідь на кліки. Рішення — Rive з State Machine. Типове завдання: кнопка 'Відправити' зі зворотним зв'язком — спочатку блимає, потім показує спіннер, потім галочку успіху. На CSS/JS це десятки рядків коду та синхронізація таймінгів. Rive з State Machine дозволяє дизайнеру закласти логіку переходів, а розробнику керувати нею з JavaScript. Ми використовуємо Rive в комерційних проектах вже понад 5 років — понад 20 успішних інтеграцій. Економія часу розробки порівняно з написанням анімацій на CSS/JS — до 60%, що може становити $500–1500 на проекті. Розмір рантайму Rive ~40 КБ gzip (за даними документації Rive) проти ~150 КБ у Lottie — це в 3,75 раза менше, що дає виграш у швидкості завантаження сторінки та покращує Core Web Vitals. Rive також підтримує події RiveEvent для зворотного зв'язку з кодом. Наприклад, можна слухати завершення анімації та відправляти аналітику. State Machine підтримує до 16 inputs, що дозволяє реалізувати складні сценарії взаємодії. Для швидкого вибору відповідного формату порівняємо Rive з Lottie за ключовими параметрами.
Що таке Rive і чому він кращий за Lottie?
| Характеристика | Rive | Lottie |
|---|---|---|
| Тип анімації | Інтерактивна (State Machine) | Лінійна (відтворення) |
| Рендеринг | WebGL / Canvas 2D (GPU) | Canvas 2D (CPU) |
| Розмір рантайму | ~40 КБ gzip (Rive docs) | ~150 КБ gzip |
| Керування з JS | Inputs (boolean, number, trigger) | Тільки play/pause/seek |
| Події | Так (RiveEvent) | Ні |
Якщо ваш проект потребує анімацій, які реагують на дії користувача (наприклад, кнопка зі зворотним зв'язком при завантаженні), Rive — найкращий вибір. Він дає повний контроль над поведінкою анімації через JavaScript, а не просто «зациклити відрізок».
Чому варто обрати Rive для інтерактивних анімацій?
Інтерактивні анімації на основі State Machine відкривають можливості, недоступні в Lottie: реагування на hover, клік, введення даних. Rive підтримує три типи inputs (Boolean, Number, Trigger), що дозволяє прив'язати анімацію до будь-якої події. Наприклад, прогрес-бар може відображати реальний відсоток завантаження, а при досягненні 100% запускати тригер завершення. За нашими даними, використання Rive замість кастомних CSS-анімацій скорочує час розробки інтерактивних елементів на 50–70%.
Як State Machine робить анімації інтерактивними?
State Machine — граф переходів між анімаціями. Дизайнер створює логіку в Rive Editor, розробник керує inputs з коду. Наприклад, hover переводить анімацію в стан «наведення», клік — у «натискання». Rive State Machine — це ключова фішка, яка відрізняє Rive від Lottie. Завдяки State Machine ви можете створювати складні сценарії взаємодії без написання коду логіки.
Покрокова інтеграція Rive з React
Крок 1: Встановіть пакет
npm install @rive-app/react-canvas # або WebGL-рендерер (краще для складних сцен): npm install @rive-app/react-webgl2 Крок 2: Створіть базовий компонент
// components/RiveAnimation.tsx 'use client' import { useRive, Layout, Fit, Alignment } from '@rive-app/react-canvas' interface RiveAnimationProps { src: string stateMachine?: string animation?: string className?: string } export function RiveAnimation({ src, stateMachine, animation, className, }: RiveAnimationProps) { const { RiveComponent } = useRive({ src, stateMachines: stateMachine ? [stateMachine] : undefined, animations: animation ? [animation] : undefined, autoplay: true, layout: new Layout({ fit: Fit.Contain, alignment: Alignment.Center, }), }) return <RiveComponent className={className} /> } Крок 3: Кнопка зі зворотним зв'язком через State Machine
// components/InteractiveButton.tsx 'use client' import { useRive, useStateMachineInput } from '@rive-app/react-canvas' export function RiveButton() { const { RiveComponent, rive } = useRive({ src: '/animations/button.riv', stateMachines: 'ButtonSM', autoplay: true, }) const isHoverInput = useStateMachineInput(rive, 'ButtonSM', 'isHover') const isPressedInput = useStateMachineInput(rive, 'ButtonSM', 'isPressed') const isLoadingInput = useStateMachineInput(rive, 'ButtonSM', 'isLoading') const handleClick = async () => { if (isLoadingInput) isLoadingInput.value = true await fetch('/api/action') if (isLoadingInput) isLoadingInput.value = false } return ( <button className="relative w-48 h-14" onMouseEnter={() => isHoverInput && (isHoverInput.value = true)} onMouseLeave={() => isHoverInput && (isHoverInput.value = false)} onMouseDown={() => isPressedInput && (isPressedInput.value = true)} onMouseUp={() => isPressedInput && (isPressedInput.value = false)} onClick={handleClick} > <RiveComponent /> </button> ) } Крок 4: Керування числовими inputs та подіями
// components/ProgressRive.tsx 'use client' import { useRive, useStateMachineInput } from '@rive-app/react-canvas' interface ProgressRiveProps { progress: number // 0–100 } export function ProgressRive({ progress }: ProgressRiveProps) { const { RiveComponent, rive } = useRive({ src: '/animations/progress.riv', stateMachines: 'ProgressSM', autoplay: true, }) const progressInput = useStateMachineInput(rive, 'ProgressSM', 'progress') const completeTrigger = useStateMachineInput(rive, 'ProgressSM', 'complete', false) if (progressInput) progressInput.value = progress if (progress >= 100 && completeTrigger) completeTrigger.fire() return <RiveComponent style={{ width: 300, height: 80 }} /> } Rive також може відправляти події в JavaScript. Наприклад, при завершенні анімації або кліку на елемент. Це реалізується через підписку на EventType.RiveEvent.
Оптимізація продуктивності Rive-анімацій
При інтеграції важливо вибрати відповідний рендерер: WebGL для складних сцен з великою кількістю об'єктів, Canvas 2D для простих анімацій. WebGL використовує GPU, що знижує навантаження на CPU до 60% порівняно з Canvas 2D. Рекомендується використовувати ліниве завантаження .riv-файлів та вивантажувати анімації, коли вони не в зоні видимості. У наших проектах ми застосовуємо IntersectionObserver та ResizeObserver для адаптації під retina-екрани.
Оптимізація: ручний Canvas для максимального контролю
Якщо потрібно кілька Rive-інстанцій або кастомний цикл рендеру, використовуйте низькорівневий рантайм.
Приклад низькорівневого рантайму
// components/LowLevelRive.tsx 'use client' import { useEffect, useRef } from 'react' import Rive, { Fit } from '@rive-app/canvas' export function LowLevelRive({ src }: { src: string }) { const canvasRef = useRef<HTMLCanvasElement>(null) useEffect(() => { if (!canvasRef.current) return const r = new Rive({ canvas: canvasRef.current, src, autoplay: true, onLoad: () => { r.resizeDrawingSurfaceToCanvas() }, }) const observer = new ResizeObserver(() => { r.resizeDrawingSurfaceToCanvas() }) observer.observe(canvasRef.current) return () => { r.cleanup() observer.disconnect() } }, [src]) return ( <canvas ref={canvasRef} style={{ width: '100%', height: '100%' }} /> ) } Процес роботи та терміни
| Етап | Термін |
|---|---|
| Відтворення готового .riv | 2–3 години |
| Інтеграція State Machine + inputs | 1–2 робочі дні |
| Створення .riv-файлу (якщо немає) | Окреме завдання для дизайнера |
Вартість інтеграції розраховується індивідуально і залежить від складності анімацій та логіки State Machine. Середня економія бюджету на анімації — $1000 на проекті.
Типові помилки при інтеграції
- Неправильний fit/alignment — анімація може обрізатися
- Відсутність resizeDrawingSurfaceToCanvas — розмиття на retina
- Ігнорування події RiveEvent — втрата інтерактивності
Що входить у роботу з нами
- Створення або оптимізація .riv-файлу (за потреби)
- Інтеграція Rive State Machine з вашим React-проектом
- Налаштування inputs та подій (до 16 inputs)
- Оптимізація продуктивності (WebGL/Canvas, lazy loading)
- Документація з використання компонентів
- Тестування на різних пристроях (retina, мобільні)
- Підтримка після здачі (1 місяць)
Чому варто замовити інтеграцію в нас?
- Понад 5 років досвіду з анімаціями
- 20+ успішних інтеграцій Rive
- Гарантія якості: сертифіковані спеціалісти
- Пропонуємо інтеграцію під ключ за 2–5 днів
- Оцінимо ваш проект безкоштовно — напишіть нам!







