Типографские эффекты

Типографические эффекты в Motion One строятся вокруг манипуляции отдельными символами или группами символов с использованием анимации свойств transform, opacity, filter и spacing. Основной принцип заключается в том, что текст рассматривается не как единый блок, а как набор независимых элементов, каждый из которых может изменяться во времени с собственной задержкой, длительностью и функцией плавности.

Motion One предоставляет низкоуровневый API для анимации DOM-элементов через функцию animate. Текстовые эффекты не являются встроенной абстракцией, поэтому типографика реализуется через ручное разбиение строки на элементы.

Базовый пример анимации одного текстового блока:

import { animate } from "motion";

animate(
  "#title",
  { opacity: [0, 1], y: [20, 0] },
  { duration: 0.6, easing: "ease-out" }
);

Такой подход работает только с целым элементом. Для создания типографических эффектов текст предварительно сегментируется.

Разбиение текста на символы

Основой большинства эффектов является разбиение строки на <span>-элементы, каждый из которых содержит один символ.

const el = document.querySelector("#text");
const text = el.textContent;

el.textContent = "";

const chars = text.split("");

chars.forEach(char => {
  const span = document.createElement("span");
  span.textContent = char;
  span.style.display = "inline-block";
  el.appendChild(span);
});

Каждый символ становится независимым DOM-узлом, что позволяет применять анимацию индивидуально.

После этого можно анимировать каждый символ через Motion One.

import { animate } from "motion";

document.querySelectorAll("#text span").forEach((span, i) => {
  animate(
    span,
    { opacity: [0, 1], y: [10, 0] },
    { delay: i * 0.03, duration: 0.4 }
  );
});

Ключевой параметр здесь — delay, создающий эффект последовательного появления.

Пошаговая анимация (stagger)

Stagger-эффект формирует ритмическое появление символов, слов или строк. В Motion One нет отдельного stagger-API как в некоторых библиотеках, но эффект достигается через вычисляемую задержку.

const letters = document.querySelectorAll(".title span");

letters.forEach((letter, index) => {
  animate(
    letter,
    { opacity: [0, 1], scale: [0.8, 1] },
    {
      delay: index * 0.05,
      duration: 0.5
    }
  );
});

Для более сложной логики используется математическая модуляция задержки:

const waveDelay = (i, total) => {
  return Math.sin(i / total * Math.PI) * 0.2;
};

letters.forEach((letter, i) => {
  animate(
    letter,
    { y: [20, 0], opacity: [0, 1] },
    {
      delay: waveDelay(i, letters.length),
      duration: 0.6
    }
  );
});

Такой подход позволяет формировать нелинейные паттерны появления текста.

Эффект печатной машинки

Эффект имитации набора текста строится на последовательном изменении прозрачности символов или постепенном добавлении DOM-элементов.

Вариант с заранее подготовленными символами:

const chars = document.querySelectorAll("#typewriter span");

chars.forEach((char, i) => {
  animate(
    char,
    { opacity: [0, 1] },
    {
      delay: i * 0.08,
      duration: 0.01
    }
  );
});

Более динамическая версия без предварительной разметки:

const el = document.querySelector("#typewriter");
const text = el.textContent;

el.textContent = "";

let i = 0;

function type() {
  if (i < text.length) {
    const span = document.createElement("span");
    span.textContent = text[i];
    el.appendChild(span);

    animate(span, { opacity: [0, 1], y: [5, 0] }, { duration: 0.2 });

    i++;
    requestAnimationFrame(type);
  }
}

type();

Подобный подход позволяет сочетать DOM-мутацию и анимацию в реальном времени.

Анимация появления с blur и opacity

Типографические эффекты часто включают работу с фильтрами. Размытие позволяет создавать эффект фокуса или проявления текста.

document.querySelectorAll(".blur-text span").forEach((span, i) => {
  animate(
    span,
    {
      opacity: [0, 1],
      filter: ["blur(10px)", "blur(0px)"]
    },
    {
      delay: i * 0.04,
      duration: 0.6
    }
  );
});

Комбинация blur и transform создаёт эффект “проявления из глубины”:

animate(
  span,
  {
    opacity: [0, 1],
    scale: [1.1, 1],
    filter: ["blur(8px)", "blur(0px)"]
  },
  { duration: 0.7 }
);

Трансформации tracking и letter-spacing

Манипуляции межбуквенным расстоянием используются для создания эффекта сборки текста из хаоса.

animate(
  "#headline",
  {
    letterSpacing: ["0.5em", "0em"],
    opacity: [0, 1]
  },
  {
    duration: 0.8,
    easing: "ease-out"
  }
);

В более сложных сценариях letter-spacing комбинируется с разбиением на символы:

document.querySelectorAll("#headline span").forEach((span, i) => {
  animate(
    span,
    {
      transform: ["translateX(10px)", "translateX(0px)"],
      opacity: [0, 1]
    },
    {
      delay: i * 0.02,
      duration: 0.4
    }
  );
});

Такая комбинация создаёт эффект «сжатия» текста в финальную форму.

Волновые эффекты

Волновая анимация строится на синусоидальном распределении задержек или смещений. Каждый символ получает уникальное смещение по оси Y или фазовую задержку.

const letters = document.querySelectorAll(".wave span");

letters.forEach((letter, i) => {
  const offset = Math.sin(i * 0.5) * 10;

  animate(
    letter,
    {
      y: [offset + 20, offset],
      opacity: [0, 1]
    },
    {
      delay: i * 0.02,
      duration: 0.5
    }
  );
});

Более выраженный эффект достигается при использовании временной функции внутри интервала:

letters.forEach((letter, i) => {
  animate(
    letter,
    {
      y: [30, 0]
    },
    {
      delay: i * 0.03,
      duration: 0.6,
      easing: t => Math.sin(t * Math.PI)
    }
  );
});

Такой тип easing формирует нелинейное движение, усиливающее ощущение волны.

Синхронизация с scroll

Motion One поддерживает scroll-based анимации через inView и scroll утилиты. Типографические эффекты часто активируются при попадании текста в область видимости.

import { inView, animate } from "motion";

inView("#section-title", ({ target }) => {
  target.querySelectorAll("span").forEach((span, i) => {
    animate(
      span,
      { opacity: [0, 1], y: [15, 0] },
      { delay: i * 0.03, duration: 0.5 }
    );
  });
});

Scroll-триггеры позволяют избегать лишних вычислений до момента появления элемента.

Для более точного контроля используется scroll прогресс:

import { scroll, animate } from "motion";

scroll(({ y }) => {
  const progress = y.progress;

  document.querySelectorAll("#text span").forEach((span, i) => {
    span.style.opacity = Math.min(1, Math.max(0, progress * 2 - i * 0.02));
  });
});

Здесь анимация напрямую зависит от позиции прокрутки.

Комбинированные эффекты

На практике типографические эффекты редко существуют изолированно. Чаще всего применяется комбинация нескольких техник: stagger, blur, transform и opacity.

document.querySelectorAll(".combo span").forEach((span, i) => {
  animate(
    span,
    {
      opacity: [0, 1],
      y: [20, 0],
      filter: ["blur(6px)", "blur(0px)"],
      scale: [0.95, 1]
    },
    {
      delay: i * 0.025,
      duration: 0.6
    }
  );
});

Сочетание параметров формирует многослойную динамику появления текста, где каждый символ проходит несколько стадий трансформации.

Оптимизация типографических анимаций

Анимация большого количества символов требует внимания к производительности. Основные ограничения связаны с количеством DOM-элементов и частотой обновлений.

Оптимизационные подходы включают:

Использование transform и opacity как основных анимируемых свойств, поскольку они не вызывают layout recalculation.

Снижение количества DOM-узлов через группировку символов в слова:

const words = text.split(" ");

words.forEach(word => {
  const wrapper = document.createElement("span");
  wrapper.className = "word";

  wrapper.textContent = word;
  el.appendChild(wrapper);
});

Анимация слов вместо символов снижает нагрузку на рендеринг.

Применение will-change для подготовки слоя композитинга:

span {
  will-change: transform, opacity;
}

Минимизация количества одновременных активных анимаций также влияет на стабильность кадровой частоты.


Типографические эффекты в Motion One формируются на основе комбинации DOM-декомпозиции, временных задержек и анимации базовых визуальных свойств. Гибкость библиотеки позволяет строить как простые эффекты появления, так и сложные многослойные текстовые сцены с нелинейной динамикой и привязкой к пользовательскому взаимодействию.