Recently the framework Angular launched exiciting features in the V17 version, in this article we will learn how to start using the View Transition API. This feature does not have good documentation, the idea here is to explain in practice.
In the demo project, we simulate a list of products, and when the user selects one, the application opens a new route with a smooth transition.
The View Transitions API is still experimental in both (browsers and Angular), you can check the actual support here https://caniuse.com/view-transitions.
Without View Transition enabled
Enabling View Transition with Angular
The first thing you need to do is to include the withViewTransitions()
along with the proviceRouter
.
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'product/:id', component: ProductComponent },
];
bootstrapApplication(App, {
providers: [provideRouter(routes, withViewTransitions())],
});
With default View Transition effect
Customizing the default animation
@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;
}
Animating isolated elements
Is important that each element have a unique name, in a @for
example, if you set the same name for each element in the loop, the view transition will not work.
html
<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>
In the path "/", our list have a loop of products, in each item, we will add:
html
<img
[style.view-transition-name]="returnViewTransition(product.id)"
src="https://picsum.photos/id/63/367/267"
/>
As mentioned, we need to respect that only one element will have the property view-transition-name: banner
, this little method will ensure to return it at the right moment. My strategy here was:
- Create a small service inject root with a parameter signal to store the current id that the user is navigating with the cursor.
-
returnViewTransition
will return dinamic based on the comparison of the product id in the loop and the current id in the signal.
Inside the /product/:id
route, we have this block:
html
<header class="hero">
<img src="https://picsum.photos/id/63/1280/720" />
<button class="close-btn" routerLink="/">Back</button>
</header>
Now we need to tell the browser the view-transition-name
associated with the home image:
css
.hero img {
width: 100%;
view-transition-name: banner;
}
Final result
Demo project
https://stackblitz.com/edit/stackblitz-starters-ba6uus?file=src%2Fpages%2Fhome%2Fhome.component.html
Top comments (0)