Lit — современный фреймворк для создания веб-компонентов на JavaScript, обеспечивающий декларативное обновление DOM с высокой производительностью. Работа с анимациями и переходами в Lit строится на сочетании стандартных CSS-технологий и встроенных возможностей жизненного цикла компонентов. Понимание этих механизмов позволяет создавать плавные и отзывчивые интерфейсы.
Анимации в Lit чаще всего реализуются через CSS-транзишены и CSS-анимации, применяемые к шаблонам компонентов. Основное преимущество Lit заключается в том, что изменения DOM автоматически реагируют на обновления свойств, что позволяет синхронизировать анимации с состоянием компонента.
Пример использования CSS-перехода:
import { LitElement, html, css } from 'lit';
class FadeBox extends LitElement {
static properties = {
visible: { type: Boolean }
};
static styles = css`
div {
width: 100px;
height: 100px;
background-color: blue;
transition: opacity 0.5s ease-in-out;
opacity: 0;
}
div.visible {
opacity: 1;
}
`;
render() {
return html`
`;
}
}
customElements.define('fade-box', FadeBox);
В этом примере добавление или удаление класса visible
плавно изменяет прозрачность элемента. Lit автоматически обновляет DOM
при изменении свойства visible.
Lit предоставляет методы жизненного цикла компонента, которые полезны для реализации анимаций:
firstUpdated(changedProperties) — вызывается после
первого рендера компонента. Идеально подходит для запуска анимаций при
монтировании элемента.updated(changedProperties) — вызывается после каждого
обновления свойства. Позволяет инициировать анимацию при изменении
состояния.connectedCallback() и
disconnectedCallback() — можно использовать для
инициализации и очистки таймеров анимаций.Пример запуска анимации после рендера:
updated(changedProperties) {
if (changedProperties.has('visible') && this.visible) {
const box = this.shadowRoot.querySelector('div');
box.animate([{ transform: 'scale(0)' }, { transform: 'scale(1)' }], {
duration: 500,
easing: 'ease-out'
});
}
}
Метод animate использует Web Animations
API, позволяя создавать сложные анимации без дополнительных
библиотек.
Для динамических списков или условного рендера важны переходы появления и исчезновения элементов. В Lit это реализуется через сочетание условного рендера и CSS-анимаций:
render() {
return html`
${this.items.map(
item => html`
${item}
`
)}
`;
}
static styles = css`
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.item {
margin: 5px 0;
}
`;
Использование CSS-анимации @keyframes позволяет плавно
визуализировать появление элементов в списке.
Lit позволяет связывать состояние компонента с анимациями, создавая интерактивные интерфейсы. Например, анимация можно запускать в зависимости от свойства:
render() {
return html`
`;
}
static styles = css`
.box {
width: 100px;
height: 100px;
background: red;
transition: all 0.5s ease;
}
.box.open {
transform: translateX(100px) rotate(20deg);
background: green;
}
.box.closed {
transform: translateX(0) rotate(0);
background: red;
}
`;
Изменение свойства toggle автоматически обновляет DOM и
инициирует переход.
requestUpdateИногда необходимо контролировать порядок анимаций или отложенные
обновления. Метод requestUpdate позволяет вручную
инициировать реактивное обновление, что полезно для цепочек
анимаций:
async triggerAnimation() {
this.state = 'start';
await this.updateComplete;
this.state = 'end';
}
updateComplete — промис, который завершается после
следующего рендера компонента, что обеспечивает синхронизацию анимации с
DOM.
Для сложных анимаций важно учитывать:
transform и opacity
вместо top/left — эти свойства анимируются GPU и
не вызывают пересчет макета.transition: all может снижать производительность.Lit позволяет комбинировать эти подходы с реактивностью компонентов, создавая плавные и отзывчивые интерфейсы даже при большом числе элементов.