Skip to content

Анимации ​

FLIP-анимирует transform при пересчёте раскладки вместо телепортации элементов, и проявляет/скрывает недавно смонтированные/удалённые карточки — всё целиком через инлайн-стили, так что это работает без обязательного CSS.

Опции ​

MasonryOptions.animate / transitionDuration / transitionEasing

animate ​

boolean · по умолчанию: true

Включает или полностью выключает описанную ниже анимацию. При false каждое изменение позиции применяется мгновенно, без перехода и без проявления.

transitionDuration ​

number (мс) · по умолчанию: 250

Игнорируется при выключенном animate.

transitionEasing ​

string · по умолчанию: 'cubic-bezier(0.2, 0, 0, 1)'

Любое допустимое значение CSS transition-timing-function. Игнорируется при выключенном animate.

Пример:

ts
const engine = createMasonryEngine(container, {
  animate: true, // дефолт — указан явно для наглядности
  transitionDuration: 400, // медленнее дефолтных 250мс
  transitionEasing: 'ease-out', // обычное ключевое слово вместо дефолтного cubic-bezier
})

Алгоритм работы анимации ​

  • Первая расстановка — самая первая позиция карточки применяется мгновенно (без перехода), вместе с opacity: 0 и классом mk-item-enter, а чуть позже (после одного общего принудительного reflow, объединённого для всех карточек, входящих в этом же проходе) opacity переходит к 1. Без этого двухшагового коммита свежесмонтированная карточка визуально «влетала» бы из координаты начала отсчёта вместо того, чтобы просто проявиться на своём реальном месте.
  • Каждая расстановка после первой FLIP-анимируется: элемент уже сидит на старом transform, движок одновременно задаёт transition и новый transform, а браузер анимирует разницу — карточки визуально съезжают на новое место вместо скачка.
  • Удаление плавно снижает opacity до 0 на элементе, к которому карточка резолвится в данный момент (добавляется класс mk-item-leave), но не задерживает реальное удаление элемента из DOM — ядро не владеет этим жизненным циклом, этим занимается адаптер фреймворка. <MasonryGrid> (и Vue-компонент, и React) держит обёртку удалённой карточки смонтированной ещё transitionDuration после того, как она исчезла из items, именно для того, чтобы это проявление успело отыграть, а не обрывалось на середине.
  • Никакого scale() при входе/выходе — намеренно. Сопутствующий scale() пробовали и отказались от него — он меняет отрисованный размер карточки так, что математика отступов/позиций это не учитывает, что читается как ошибка самого layout'а в отступах, хотя реальные позиции никогда не менялись. Одна только прозрачность этого избегает.
  • No-op transform полностью пропускается — если посчитанная позиция карточки на самом деле не изменилась с прошлого пересчёта, ничего не трогается, так что у статичной карточки нагрузка от слушателя transitionend/will-change остаётся нулевой.
  • will-change: transform задаётся на время перехода двигающейся карточки и снимается (will-change: auto) сразу после срабатывания её transitionend — никогда не держится открытым бесконечно, что избегает классической проблемы will-change с памятью/композитными слоями.

CSS-хуки ​

Три класса переключаются на собственном элементе карточки для стилизации поверх встроенной анимации transform/opacity:

КлассКогда
.mk-item-enterПрименяется при первой расстановке карточки, вместе с проявлением.
.mk-item-movingПрименяется, пока карточка FLIP-переходит на новую позицию.
.mk-item-leaveПрименяется, когда карточка начинает исчезать после удаления.

Когда animate включён, на контейнер также задаются две CSS custom property, отражающие посчитанные длительность/easing — чтобы ваш собственный CSS (например, hover-эффект) мог использовать то же самое время, не дублируя его отдельно. Собственная анимационная логика ядра использует посчитанные JS-значения напрямую, не эти переменные — они удобство для ваших стилей, а не то, что ядро читает обратно:

css
.mk-item {
  /* собственный переход, синхронизированный с таймингом masonry-kit */
  transition: box-shadow var(--mk-transition-duration) var(--mk-transition-easing);
}