Skip to main content
Зміст гайду

Зміст гайду

Час на вивчення: 14 хв
#automation#animated#video#scroll#creative-coding#frontend
Середній14 хв

Анімовані скрол-сайти з відео: повний посібник зі створення

Як створити преміальний сайт з ефектом скрол-відео (Apple-style): нарізка кадрів у WebP, LERP-згладжування на Canvas, dwell-remap та редакційна система Precision Editorial.

Опубліковано:

Animated Video Scroll — це техніка створення кінематографічних односторінкових сайтів, де прокрутка сторінки безпосередньо керує відтворенням відеоматеріалу. Коли користувач гортає сторінку колесом миші або свайпом по екрану смартфона, відео плавно змінюється кадр за кадром, синхронізуючись із темпом читання та появою інформаційних блоків.

Цей ефект став візитівкою презентацій преміальних продуктів Apple, Tesla, Porsche та провідних дизайн-студій світу.

Важливо

Ця техніка не є вбудовуванням звичайного відеоплеєра і не використовує анімовані GIF. В її основі лежить покадрова послідовність легких WebP-зображень, які апаратно відмальовуються на елементі <canvas> через WebGL або 2D Context, гарантуючи миттєвий відгук на кожен піксель скролу.


1. Що таке скрол-сайт із відео та його переваги

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

Скрол-керований сайт вирішує цю проблему:

  • Повний контроль уваги: Користувач сам обирає темп перегляду. Якщо він зупиняється на важливому абзаці, об'єкт у кадрі завмирає у потрібному ракурсі.
  • Відсутність затримок і буферизації: Відеофайл заздалегідь розбивається на оптимізовані статичні кадри WebP, тому браузеру не потрібно виконувати важке декодування контейнерів MP4 під час швидкого скролу.
  • Синхронізація наративу: Текстові тези, графічні мітки, числові метрики та технічні специфікації з'являються саме тоді, коли камера демонструє відповідну деталь об'єкта.

Відповідність типу проєкту

Тип продуктуЧому підходить скрол-відеоКлючовий фокус у кадрі
Автомобілі та технікаПідкреслює аеродинаміку, деталі шасі, матеріали салонуПлавний рух камери вздовж кузова, зміна ракурсів
Преміальна електронікаДемонструє прецизійну збірку, товщину корпусу, оптикуРозбирання на компоненти (exploded view), макрозйомка
Архітектура та нерухомістьСтворює просторове відчуття об'єму та освітленняПроліт крізь фасад у внутрішній інтер'єр
Fashion та ювелірні виробиПоказує текстуру тканини, гру світла на металіДелікатний рух світла навколо виробу

2. Архітектура та структура файлів навички

Навичка побудована як модульний інженерний конвеєр. Кожен компонент відповідає за свій ізольований етап роботи:

text
animated-sites-engine/ ├── SKILL.md # Сценарна інструкція: від аналізу ролика до верстки ├── visual-system.md # Дизайн-система Precision Editorial та правила сітки ├── extract_frames.py # Python-утиліта нарізки та оптимізації WebP └── evals.json # Бенчмарк та критерії перевірки якості сайту

1. SKILL.md — головна інструкція та сценарний алгоритм

Описує життєвий цикл створення сторінки: від технічного аналізу вихідного матеріалу за допомогою ffprobe до структуризації на смислові глави, розрахунку тривалості скролу та збірки готового HTML/JS додатку.

2. visual-system.md — довідник системи Precision Editorial

Встановлює суворі естетичні правила: відмова від дешевих штампів (безпідставних неонових світінь, скляних плашок і шрифту Playfair), готова палітра «Trackline» для технічних сюжетів, 5 базових схем розміщення тексту та типографічні пари.

3. extract_frames.py — скрипт екстракції та стиснення кадрів

Консольна утиліта на Python. Автоматично зчитує метадані відео через ffprobe, розраховує пропорційну кількість кадрів, нарізає окремі потоки під Desktop і Mobile у форматі WebP та генерує manifest.json.

4. evals.json — сценарії верифікації якості

Містить тестовий еталонний кейс (на прикладі ролика Porsche), що перевіряє плавність LERP, поведінку canvas при зміні розміру вікна, доступність для клавіатури та вагу асетів.


3. Механіка відтворення: Canvas, LERP та Dwell-Remap

В основі роботи лежить елемент <canvas>, закріплений на весь екран (position: fixed). Прокрутка сторінки перераховується у відносний прогрес від 0.0 до 1.0, який визначає, який саме номер кадру має відображатися.

text
Позиція скролу (0.0 — 1.0) │ ▼ ┌───────────────────────┐ │ Dwell-Remap │ ──► Штучне сповільнення біля центрів глав └──────────┬────────────┘ │ ▼ ┌───────────────────────┐ │ LERP-фільтр │ ──► targetFrame плавним кроком наздоганяє скрол └──────────┬────────────┘ │ ▼ ┌───────────────────────┐ │ HTML5 2D Canvas │ ──► ctx.drawImage(loadedImages[frameIndex], ...) └───────────────────────┘

1. Згладжування через LERP (Linear Interpolation)

Якщо перемикати кадри суворо за кожним івентом скролу, анімація вийде рваною, особливо на мишах із дискретним колесом прокрутки.

Для кінематографічної плавності застосовується лінійна інтерполяція: кадр, що відмальовується на екрані (currentFrame), плавно «наздоганяє» цільовий кадр (targetFrame).

javascript
let currentFrame = 0; let targetFrame = 0; const lerpFactor = 0.075; // Коефіцієнт згладжування (0.05 — 0.1) function renderLoop() { // Наближаємо поточний кадр до цільового currentFrame += (targetFrame - currentFrame) * lerpFactor; const frameToDraw = Math.round(currentFrame); drawCanvasFrame(frameToDraw); requestAnimationFrame(renderLoop); } window.addEventListener("scroll", () => { const maxScroll = document.documentElement.scrollHeight - window.innerHeight; const progress = Math.min(Math.max(window.scrollY / maxScroll, 0), 1); targetFrame = progress * (totalFrames - 1); }, { passive: true });

2. Сповільнення біля кожної глави (Dwell-Remap)

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

javascript
function applyDwellRemap(rawProgress, chapterPoints = [0.2, 0.5, 0.8], dwellWidth = 0.08, strength = 0.45) { let remapped = rawProgress; for (const center of chapterPoints) { const distance = Math.abs(rawProgress - center); if (distance < dwellWidth) { // Плавне згасання коефіцієнта швидкості по косинусоїді const factor = Math.cos((distance / dwellWidth) * (Math.PI / 2)); const delta = (rawProgress - center) * (1 - factor * strength); remapped = center + delta; break; } } return Math.min(Math.max(remapped, 0), 1); }

3. Прогресивне завантаження кадрів

Щоб уникнути білих спалахів і не чекати завантаження всього пакета (100–150 кадрів), застосовується двоетапна стратегія:

  1. Критичний пріоритет: Миттєво завантажуються перші 5 кадрів та опорні кадри ключових глав.
  2. Фонова черга: Решта кадрів підтягуються невеликими партіями через requestIdleCallback або чергу промісів. Якщо потрібний кадр ще в дорозі, canvas відображає найближчий уже завантажений.

4. Покроковий процес розробки: від відео до коду

Весь виробничий процес розбитий на сім послідовних кроків:

Крок 1. Аналіз ролика за допомогою ffprobe

Перед генерацією коду аналізуються технічні параметри вихідного файлу:

bash
ffprobe -v error -select_streams v:0 \ -show_entries stream=width,height,duration,r_frame_rate,codec_name \ -of default=noprint_wrappers=1 input.mp4

Створюється контактний лист із 6 опорних кадрів, щоб оцінити рух камери, положення об'єкта та наявність вільного місця (negative space) під текст.

Крок 2. Формулювання дизайн-концепції

Формулюється чітка теза:

  • Головний герой: Хто або що в центрі уваги.
  • Цільова емоція: Технічна точність, спокійна розкіш, драйв, медитативність.
  • Шрифтова пара: Контрастний заголовок та інженерний моноширинний акцент.
  • Фірмовий прийом: Телеметрія, змінний трекінг, лічильник мікрокадрів.

Крок 3. Нарізка та оптимізація кадрів

Кількість кадрів та висота прокрутки підбираються відповідно до хронометражу відео:

Тривалість відеоКількість кадрівРекомендована висота скролуСумарна цільова вага (WebP)
0–5 секунд60–80 кадрів450–550vh4–7 МБ
5–15 секунд90–130 кадрів600–750vh8–12 МБ
15–30 секунд130–180 кадрів750–900vh10–15 МБ
30+ секунд180–200 кадрів900–1000vh12–16 МБ

Запуск екстракції через Python-скрипт:

bash
python3 extract_frames.py \ --input ./raw/porsche-gt3.mp4 \ --output ./public/frames \ --desktop-frames 120 \ --mobile-frames 80 \ --quality 62

Крок 4. Сценарій за главами

Сторінка ділиться на 4–6 змістовних розділів. Наприклад:

  1. Глава 1: Вступ (0–15%) — Назва моделі, мінімалістичний силует.
  2. Глава 2: Аеродинаміка (20–40%) — Фокус на геометрії антикрила та повітропроводів.
  3. Глава 3: Силова установка (45–65%) — Показ двигуна або шасі з телеметричними даними.
  4. Глава 4: Фінал і дія (75–100%) — Повне розкриття автомобіля та кнопка тест-драйву.

Крок 5. Композиція шарів та верстка навколо відео

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

Крок 6. Збірка на основі стартового шаблону

Використовується надійний HTML5-каркас із готовою логікою підвантаження та підтримкою адаптивності, до якого підключаються індивідуальні токени кольорів та маніфест кадрів.

Крок 7. Перевірка та критика

Порада

Завжди тестуйте скрол-сайти через локальний HTTP-сервер (python3 -m http.server), а не відкриваючи файл напряму через file:///. Браузерні політики CORS блокують завантаження WebP-кадрів через fetch() при локальному відкритті файлів.


5. Візуальна система: типографіка та палітра Trackline

Система Precision Editorial вимагає відмови від декоративних надмірностей на користь вивіреної швейцарської верстки та естетики приладів контролю.

Типографічні комбінації

  • Заголовки: Archivo (Black, Tight tracking -0.03em)
  • Основний текст: Archivo (Regular, 15px)
  • Технічні підписи та телеметрія: IBM Plex Mono (Medium, 11px, Uppercase)
  • Найкраще для: Автомобілі, авіація, важка інженерія, годинникові механізми.

Колірна палітра «Trackline»

Палітра будується на кольорах справжнього треку: матовий карбон, холодний алюміній та стримані гоночні акценти.

css
:root { /* Базові відтінки */ --color-carbon: #080a09; /* Глибокий чорний вуглепластик (основний фон) */ --color-paper: #f1f0e9; /* Теплий матовий білий (основний текст) */ --color-alloy: #a8aca8; /* Металевий алюміній (другорядні підписи) */ --color-track: #414541; /* Графітовий асфальт (межі сітки, розділювачі) */ /* Акцентні інженерні маркери */ --color-petrol: #12372d; /* Глибокий петролеум для підкладок карток */ --color-signal: #d9381e; /* Гоночний червоний (активні стани, алерти) */ --color-heritage: #c5a059; /* Золотистий колір для прогрес-бару та таймінгу */ }
Примітка

Сигнальні кольори (--color-signal та --color-heritage) використовуються точково — для позначення активної глави або індикатора положення, займаючи не більше 3% площі екрана.


6. Композиція шарів, рух та фірмові прийоми

Сторінка конструюється з трьох незалежних за візуальною глибиною шарів:

text
┌─────────────────────────────────────────────────────────────┐ │ 3. Шар інтерфейсу: прогрес-бар, індикатор глави, кнопки дій │ ├─────────────────────────────────────────────────────────────┤ │ 2. Інформаційний шар: заголовок, опис, блок телеметрії │ ├─────────────────────────────────────────────────────────────┤ │ 1. Canvas-шар: повноекранне відео з LERP-рендерингом │ └─────────────────────────────────────────────────────────────┘

5 варіантів компонування тексту

Схема компонуванняРозташування контентуОптимальний сценарій використання
Masthead StatementГігантський заголовок на весь екран по центруВідкриваючий перший екран (вступ до ролика)
Side Margin AnnotationВузька колонка (3–4 cols) праворуч або ліворучОб'єкт рухається у протилежній частині кадру
Split StatementЗаголовок ліворуч, технічний опис праворучОб'єкт стабільно зафіксований суворо по центру
Telemetry DockГоризонтальна плашка внизу з приладовими данимиДемонстрація динаміки, швидкості, потужності
Final CalloutСфокусований блок із єдиною головною дією (CTA)Завершальний екран після завершення відеоряду

Принципи анімації DOM-елементів

Оскільки саме відео на canvas уже створює інтенсивний рух, анімація текстових блоків має бути стриманою:

  • Поява через маску: Текст піднімається знизу через контейнер з overflow: hidden.
  • Зсув: Не більше 16–24px по осі Y.
  • Таймінги: 600–800ms на вхід глави з кривою cubic-bezier(0.16, 1, 0.3, 1).
  • Жодних розмить: Фільтр filter: blur() суворо заборонений — він викликає перерахунок шарів браузера та руйнує стабільні 60 FPS.

7. Антипатерни: відмова від застарілих «люксових» штампів

Більшість шаблонних відеолендінгів виглядають дешево через набір типових дизайнерських кліше. Ось від чого слід повністю відмовитися:

Застарілий штампЧому це поганоПрофесійна альтернатива
Playfair Display + тонкий гротескСтандартний шаблон «псевдолюксу»Прецизійні гротески: Archivo, Roboto Flex, Manrope
Glassmorphism (матове скло)Розмиває фонове відео, перевантажує GPUКонтрастний чистий текст у вільному просторі кадру
Плаваючі частинки та пилВідволікають увагу від реального об'єктаЧистий canvas без штучного декоративного сміття
Фіолетово-сині неонові градієнтиАсоціюються з шаблонними криптолендінгамиНатуральні кольори, узяті безпосередньо з кадрів відео
Кастомний курсор із затримкоюСтворює відчуття лагу та незручний у роботіНативний системний курсор зі зрозумілими ховерами

8. Продуктивність, доступність (A11y) та мобільна оптимізація

Скрол-сайти з великою кількістю графіки потребують ретельної технічної дисципліни:

1. Обмеження Device Pixel Ratio (DPR)

Сучасні смартфони мають екрани з DPR 3.0 або 3.5. Якщо рендерити canvas у такій роздільній здатності, площа обчислень зростає майже в 10 разів, що миттєво перегріває процесор.

javascript
// Обмежуємо максимальний DPR значенням 2.0 const dpr = Math.min(window.devicePixelRatio || 1, 2); canvas.width = window.innerWidth * dpr; canvas.height = window.innerHeight * dpr; ctx.scale(dpr, dpr);

2. Пауза рендерингу для прихованих вкладок

Коли користувач перемикається на іншу вкладку, рендеринг має миттєво зупинятися:

javascript
document.addEventListener("visibilitychange", () => { if (document.hidden) { cancelAnimationFrame(animationFrameId); } else { requestAnimationFrame(renderLoop); } });

3. Режим зменшеної анімації (prefers-reduced-motion)

Для людей із чутливим вестибулярним апаратом постійна покадрова прокрутка може викликати запаморочення.

Важливо

Якщо в операційній системі увімкнено параметр prefers-reduced-motion: reduce, замість нескінченної прокрутки кадрів сайт має відобразити один якісний статичний постер або спрощену слайд-галерею.

css
@media (prefers-reduced-motion: reduce) { .scroll-container { height: auto !important; } canvas { display: none !important; } .static-hero-fallback { display: block !important; } }

9. Практичний воркшоп: створення та запуск проєкту

Створимо мінімальну робочу структуру скрол-сайту.

Крок 1. Генерація кадрів із відео

Помістіть відео в робочу теку та запустіть нарізку:

bash
mkdir my-scroll-site && cd my-scroll-site python3 extract_frames.py --input sample.mp4 --output ./frames --desktop-frames 120

Скрипт створить файл маніфесту frames/manifest.json:

json
{ "totalFrames": 120, "desktop": { "pathPattern": "frames/desktop/frame-%04d.webp", "width": 1920, "height": 1080, "totalWeightMb": 9.4 }, "recommendedScrollVh": 700 }

Крок 2. Структура файлів готового проєкту

text
my-scroll-site/ ├── index.html # Розмітка та логіка canvas-плеєра ├── styles.css # Токени Precision Editorial та медіазапити ├── app.js # LERP-цикл, dwell-remap та обробка скролу └── frames/ ├── desktop/ # frame-0001.webp ... frame-0120.webp ├── mobile/ # frame-0001.webp ... frame-0080.webp └── manifest.json # Метадані та розміри

Крок 3. Запуск локального середовища

Для коректного підвантаження ресурсів запустіть локальний HTTP-сервер:

bash
python3 -m http.server 3000

Відкрийте у браузері адресу http://localhost:3000 і перевірте плавність ходу кадрів та коректність перемикання глав.


10. Підсумковий чек-лист готовності скрол-сайту

Перед релізом проєкту перевірте відповідність усім інженерним та візуальним критеріям:

Технічні метрики

  • Сумарна вага кадрів десктопної версії не перевищує 12 МБ (мобільна — до 5 МБ).
  • Перші 5 кадрів мають пріоритетне передзавантаження (preload).
  • Коефіцієнт DPR обмежений значенням 2 для запобігання перегріву мобільних пристроїв.
  • Цикл requestAnimationFrame зупиняється при переході на іншу вкладку браузера.

Досвід користувача та доступність

  • Реалізовано плавний LERP-перехід між кадрами без різких ривків.
  • Налаштовано Dwell-Remap для комфортного читання тексту біля кожної глави.
  • Підтримується режим prefers-reduced-motion зі статичним постером.
  • Мінімальний розмір усіх клікабельних елементів становить щонайменше 44×44px.

Дизайн та естетика

  • Використано чітку інженерну шрифтову пару без псевдолюксових кліше.
  • Текст не перекриває головний рухомий об'єкт у кадрі.
  • Кольори інтерфейсу безпосередньо запозичені з матеріалу ролика.
  • Сторінка завершується зрозумілим, однозначним закликом до дії (CTA).
Цей гайд повністю безкоштовний. Якщо він зекономив вам вечір — ви можете підтримати розвиток проєкту.
Підтримати автора