Маски и клиппинг

В интерфейсной анимации маскирование и клиппинг используются для управления видимостью элементов без изменения их состояния в DOM-структуре. В контексте Popmotion это достигается не встроенной абстракцией, а комбинацией анимации свойств DOM, CSS и SVG через styler, tween, spring, keyframes и функциональные утилиты управления значениями.


Самый простой механизм ограничения видимой области строится на свойстве overflow: hidden. Оно превращает любой контейнер в маску прямоугольной формы, внутри которой можно анимировать содержимое.

import { styler, tween, easing } from 'popmotion';

const container = styler(document.querySelector('.container'));
const content = styler(document.querySelector('.content'));

tween({
  from: { y: 100 },
  to: { y: 0 },
  duration: 600,
  ease: easing.cubicBezier(0.2, 0.8, 0.2, 1)
}).start(v => {
  content.set('y', v.y);
});

При фиксированной высоте контейнера и overflow: hidden создаётся эффект появления снизу вверх. Такой подход применяется в раскрывающихся списках, карточках и базовых переходах.

Ключевая особенность — отсутствие вычислительной нагрузки на сложные графические операции. Клиппинг происходит на уровне рендеринга браузера.


Динамическое раскрытие через clip-path

clip-path позволяет задавать произвольные области видимости, включая анимацию геометрических форм.

Часто используется прямоугольное раскрытие:

import { tween, easing } from 'popmotion';

const element = document.querySelector('.panel');

tween({
  from: { progress: 0 },
  to: { progress: 1 },
  duration: 700,
  ease: easing.easeOut
}).start(v => {
  element.style.clipPath = `
    inset(${(1 - v.progress) * 100}% 0 0 0)
  `;
});

При изменении inset создаётся эффект вертикального или горизонтального «разворачивания».

Радиальные маски

Более сложный вариант — радиальный клиппинг:

tween({
  from: 0,
  to: 100,
  duration: 800
}).start(v => {
  element.style.clipPath = `circle(${v}% at 50% 50%)`;
});

Такой тип маски используется для эффектов «вспышки», раскрытия карточек и акцентных переходов.


SVG clipPath и анимация геометрии

SVG предоставляет более точный контроль над формой маски. В Popmotion удобно анимировать атрибуты элементов <clipPath>.

<svg width="0" height="0">
  <clipPath id="reveal">
    <rect id="mask-rect" x="0" y="0" width="0" height="100" />
  </clipPath>
</svg>

<div class="box"></div>
import { tween } from 'popmotion';

const rect = document.querySelector('#mask-rect');
const box = document.querySelector('.box');

box.style.clipPath = 'url(#reveal)';

tween({
  from: 0,
  to: 300,
  duration: 900
}).start(v => {
  rect.setAttribute('width', v);
});

SVG-клиппинг даёт точность пиксельного уровня и позволяет создавать сложные формы раскрытия, включая диагонали, волны и составные фигуры.


Маскирование через mask-image

CSS-маски позволяют использовать изображения или градиенты для управления прозрачностью. Popmotion применяется для анимации параметров маски.

import { tween } from 'popmotion';

const element = document.querySelector('.photo');

tween({
  from: 0,
  to: 1,
  duration: 1000
}).start(v => {
  element.style.webkitMaskImage = `
    linear-gradient(to right, rgba(0,0,0,${v}) 0%, rgba(0,0,0,1) 100%)
  `;
});

Такой подход используется для плавного проявления изображений с мягкими краями.

Градиентная маска позволяет управлять не только видимостью, но и плотностью появления, создавая эффект растворения.


Анимация маски как отдельного слоя

Распространённая техника — использование отдельного DOM-слоя в роли маски. Этот слой анимируется Popmotion и физически перекрывает контент.

<div class="wrapper">
  <div class="mask"></div>
  <div class="content"></div>
</div>
import { styler, spring } from 'popmotion';

const mask = styler(document.querySelector('.mask'));

spring({
  from: { scaleX: 1 },
  to: { scaleX: 0 },
  stiffness: 120,
  damping: 20
}).start(v => {
  mask.set(v);
});

При transform-origin: left создаётся эффект «сдвигающейся шторки». Такой способ часто оказывается быстрее, чем clip-path, так как использует GPU-трансформации.


Маскирование через transform-origin и scale

Семантически это не маска, но визуально эквивалентный эффект достигается через масштабирование.

import { tween } from 'popmotion';

const panel = document.querySelector('.panel');

tween({
  from: 0,
  to: 1,
  duration: 500
}).start(v => {
  panel.style.transform = `scaleY(${v})`;
});

При установке transform-origin: top элемент раскрывается сверху вниз, имитируя клиппинг.

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


Комбинированные маски

Сложные интерфейсы используют комбинации нескольких техник:

  • overflow: hidden для контейнеров
  • transform для GPU-анимации
  • clip-path для геометрической точности
  • SVG-маски для сложных форм
  • градиентные маски для мягких переходов

Пример комбинированного раскрытия карточки:

import { timeline, tween } from 'popmotion';

const card = document.querySelector('.card');
const image = document.querySelector('.card__image');

timeline([
  tween({
    from: { y: 40, opacity: 0 },
    to: { y: 0, opacity: 1 },
    duration: 300
  }),
  tween({
    from: 0,
    to: 1,
    duration: 600
  })
]).start(v => {
  card.style.transform = `translateY(${v[0].y}px)`;
  card.style.opacity = v[0].opacity;

  image.style.clipPath = `inset(${(1 - v[1]) * 100}% 0 0 0)`;
});

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


Маски, зависящие от координат

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

import { value, pointer } from 'popmotion';

const mask = document.querySelector('.mask');

const pointerTracker = pointer({
  x: 0,
  y: 0
}).start(v => {
  mask.style.clipPath = `circle(120px at ${v.x}px ${v.y}px)`;
});

Подобные эффекты применяются в интерактивных подсветках и локальных reveal-анимациях.


Производительность и ограничения

Маскирование имеет разную стоимость вычислений:

  • transform и opacity — минимальная нагрузка, оптимальны для частых анимаций
  • overflow: hidden — практически нулевая стоимость, ограничена прямоугольной формой
  • clip-path — средняя нагрузка, зависит от сложности формы
  • mask-image — высокая нагрузка при сложных градиентах и больших элементах
  • SVG clipPath — вариативная стоимость, зависит от DOM и перерисовки

При построении анимационных систем на Popmotion выбор техники маски напрямую влияет на стабильность FPS.


Анимация появления слоёв через маску-«шторку»

Распространённый паттерн — движение маски как отдельного слоя, перекрывающего контент:

import { tween, easing } from 'popmotion';

const curtain = document.querySelector('.curtain');

tween({
  from: { x: 0 },
  to: { x: 100 },
  duration: 800,
  ease: easing.easeInOut
}).start(v => {
  curtain.style.transform = `translateX(${v.x}%)`;
});

При фиксированном контейнере создаётся эффект горизонтального открытия интерфейса.


Синхронизация масок с физическими анимациями

Popmotion spring-движок позволяет связывать маскирование с инерцией движения, что делает раскрытия менее механическими.

import { spring } from 'popmotion';

const panel = document.querySelector('.panel');

spring({
  from: 0,
  to: 1,
  stiffness: 180,
  damping: 18
}).start(v => {
  panel.style.clipPath = `inset(${(1 - v) * 100}% 0 0 0)`;
});

Физическая модель сглаживает ускорение и создаёт более естественное раскрытие маски.


Маскирование в сложных интерфейсных переходах

При переходах между экранами маска часто используется как связующее звено между состояниями:

  • фиксируется исходный элемент
  • создаётся overlay-маска
  • Popmotion управляет переходом формы
  • контент под маской заменяется во время анимации

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