Использование View Transition API в Angular Framework
Недавно фреймворк Angular запустил интересные функции в версии V17. В этой статье мы узнаем, как начать использовать API View Transition. У этой функции нет хорошей документации, идея здесь — объяснить на практике.
В демо-проекте мы моделируем список продуктов, и когда пользователь выбирает один из них, приложение открывает новый маршрут с плавным переходом.
API View Transitions все еще находится в стадии эксперимента как в браузерах, так и в Angular. Проверить фактическую поддержку можно здесь https://caniuse.com/view-transitions.
Без включенного View Transition
Включение View Transition с помощью Angular
Первое, что вам нужно сделать, это включить withViewTransitions()
вместе с proviceRouter
.
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'product/:id', component: ProductComponent },
];
bootstrapApplication(App, {
providers: [provideRouter(routes, withViewTransitions())],
});
С эффектом View Transition по умолчанию
Настройка анимации по умолчанию
@keyframes fade-in {
from {
opacity: 0;
}
}
@keyframes fade-out {
to {
opacity: 0;
}
}
::view-transition-old(root) {
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out;
}
::view-transition-new(root) {
animation: 2s cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in;
}
Анимация изолированных элементов
Важно, чтобы каждый элемент имел уникальное имя. Например @for
, если вы зададите одно и то же имя для каждого элемента в цикле, переход представления не будет работать.
<h1>Products</h1>
<div class="grid">
@for(product of products; track product.id) {
<a
routerLink="product/coffee-65324"
(mouseenter)="setCurrentId(product.id)"
class="card"
>
<header>
<img
[style.view-transition-name]="returnViewTransition(product.id)"
src="https://picsum.photos/id/63/367/267"
/>
</header>
<div class="content">
<h2 class="card__title">{{ product.name }}</h2>
<p class="card__price">$3</p>
</div>
</a>
}
</div>
В пути «/» в нашем списке есть цикл продуктов, в каждый элемент мы добавим:
<img
[style.view-transition-name]="returnViewTransition(product.id)"
src="https://picsum.photos/id/63/367/267"
/>
Как уже упоминалось, нам нужно учитывать, что только один элемент будет иметь это свойство view-transition-name: banner
, этот небольшой метод обеспечит его возврат в нужный момент. Моя стратегия здесь была:
- Создать небольшой корень внедрения службы с сигналом параметра для хранения текущего идентификатора, по которому пользователь перемещается с помощью курсора.
returnViewTransition
вернет динамический результат на основе сравнения идентификатора продукта в цикле и текущего идентификатора в сигнале.
Внутри /product/:id
маршрута у нас есть этот блок:
<header class="hero">
<img src="https://picsum.photos/id/63/1280/720" />
<button class="close-btn" routerLink="/">Back</button>
</header>
Теперь нам нужно сообщить браузеру view-transition-name
связанное с домашним изображением:
.hero img {
width: 100%;
view-transition-name: banner;
}
Конечный результат
Демо проект
https://stackblitz.com/edit/stackblitz-starters-ba6uus?file=src%2Fpages%2Fhome%2Fhome.component.html