Quick start - Angular
Framework-agnostic - call initAnimations() once the view is ready and re-call it after SPA navigation. The engine is SSR-safe (checks window) but you should still guard with isPlatformBrowser and run only on the client.
Usage - Standalone root component
js
import { Component, AfterViewInit, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { Router, NavigationEnd, RouterOutlet } from '@angular/router';
import { filter } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
})
export class AppComponent implements AfterViewInit {
constructor(
@Inject(PLATFORM_ID) private platformId: Object,
private router: Router
) {}
async ngAfterViewInit() {
if (!isPlatformBrowser(this.platformId)) return;
const { initAnimations } = await import('gclass-anims');
initAnimations();
// Re-init on SPA navigation (same as Vue router.afterEach)
this.router.events
.pipe(filter((e) => e instanceof NavigationEnd))
.subscribe(async () => {
await new Promise((r) => setTimeout(r, 0));
initAnimations();
});
}
}Alternate - afterNextRender (Angular 16+)
js
import { afterNextRender, Component, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs';
@Component({ selector: 'app-root', template: '<router-outlet />' })
export class AppComponent {
constructor(@Inject(PLATFORM_ID) pid: Object, router: Router) {
if (!isPlatformBrowser(pid)) return;
afterNextRender(() => {
import('gclass-anims').then(({ initAnimations }) => {
initAnimations();
router.events.pipe(filter(e => e instanceof NavigationEnd))
.subscribe(() => initAnimations());
});
});
}
}What's next
Add utility classes to your templates (class="appear scroll spawn-up", class="float magnet"). No directives or wrappers needed. Mark persistent layout shells with .preserve so they skip re-animation on route change.