Анимации
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.
Пример:
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-значения напрямую, не эти переменные — они удобство для ваших стилей, а не то, что ядро читает обратно:
.mk-item {
/* собственный переход, синхронизированный с таймингом masonry-kit */
transition: box-shadow var(--mk-transition-duration) var(--mk-transition-easing);
}