Bonus step 3.5: routing animations

Let’s have a little fun with animations:

We are going to add an animation on every route change. To do that, we attach an animation to the router-outlet wrapper in app.component.html:

We are introducing a new observable in MiscService called page$ – it will emit every time the page changes. This is what it looks like in misc.service.ts:

We define Page as an enum in page.enum.ts:

The values are relative URLs, that’s why we can simply do this.router.routerState.snapshot.url.slice(1) as Page conversion.

That’s all we need to trigger the animation: when page changes, we have a new value emitted by the observable. The same approach works for any sort of animation – as long as we have an observable, we can use it to trigger an Angular animation. The animation itself is defined in app.component.ts:

The cool thing about Angular animations is that we have access to both “previous” and “next” page – so when user switches from Terms of Use to Privacy Policy, we can access the previous page (Terms of Use) with :leave selector and the next page (Privacy Policy) with :enter query. We can even group the two animations together by using group. We could have different animations depending which page is the “previous” and which page is the “next” one, but we are going to have the same animation for all transitions; this is defined in transition: '* => *'means “from any value to any value”.

We have 3 instructions grouped together, let’s dissect them one by one.

First instruction is the initial state for the new page:

We are setting the new page to be outside of the visible area on the right with translateX(100%), give it a little rotation with rotate3d(1, 1, 1, -15deg) and scale it 150% with scale(1.5). We also set the opacity to 50% so the new page will fly in from the right, while scaling down to normal size, rotating and becoming opaque. The option optional: true is necessary because :enter query will only work when pages are changed and would fail on initial page rendering.

The second instruction is for the old page to fly away:

This goes in 2 steps defined in the array: first step to set style to { position: 'absolute', 'z-index': -1 } – we need this so the old page does not affect the layout. Without this step, the new page renders underneath the old one, because both exist at the time of transition, and that doesn’t look good at all. We set z-index to -1 because we want the old page to appear underneath the new one. The second instruction is to fly the old page to the left while rotating it and scaling it down.

And then finally, we reset styles for our new page with the 3rd instruction:

Here’s how this looks like when we increase the animation times by 3 seconds:

And here’s what it looks like with short animation times:

Pretty cool, right? 🙂

We also add ngx-markdown npm package in this PR to render pages Privacy Policy and Terms of Service – the markdown is generated by the lovely tool Privacy Policy Generator. The home page is just custom HTML, both in English and Russian – please check it out, hopefully the purpose of LaaS becomes more clear now.

Published by Andrew Leschinsky

Founder and tech lead.