AngularAngular 16+ · standalone components

Angular scroll animations.
Plain classes, no NgModule.

The Angular wrapper deliberately does not import @angular/core. It exposes small classes you instantiate in a component and drive from the lifecycle hooks you already write, which means no peer-dependency version matrix to satisfy and nothing to break when Angular changes its module story again.

Ref class + lifecycle hooks

Quick start.

svg-scroll-draw/angular — every sample below is written against the wrappers this package actually exports.

ScrollDrawRef in a standalone component

hero.component.ts
import { Component, ElementRef, ViewChild,
         AfterViewInit, OnDestroy } from '@angular/core';
import { ScrollDrawRef } from 'svg-scroll-draw/angular';

@Component({
  standalone: true,
  selector: 'app-hero',
  template: `
    <div #container>
      <svg viewBox="0 0 200 100">
        <path d="M10 50 Q 100 10 190 50" stroke="#111" fill="none" />
      </svg>
    </div>
  `,
})
export class HeroComponent implements AfterViewInit, OnDestroy {
  @ViewChild('container') containerRef!: ElementRef<HTMLElement>;
  private draw = new ScrollDrawRef();

  ngAfterViewInit() {
    this.draw.init(this.containerRef.nativeElement, {
      easing: 'ease-out',
      speed: 1.2,
      fade: true,
    });
  }

  ngOnDestroy() {
    this.draw.destroy();
  }
}

Counters and text

stats.component.ts
import { ScrollCounterRef, ScrollTextRef } from 'svg-scroll-draw/angular';

export class StatsComponent implements AfterViewInit, OnDestroy {
  @ViewChild('revenue') revenueRef!: ElementRef<HTMLElement>;
  @ViewChild('headline') headlineRef!: ElementRef<HTMLElement>;

  private counter = new ScrollCounterRef();
  private text    = new ScrollTextRef();

  ngAfterViewInit() {
    this.counter.init(this.revenueRef.nativeElement, { to: 48000 });
    this.text.init(this.headlineRef.nativeElement, {
      split: 'words', stagger: 0.05,
    });
  }

  ngOnDestroy() {
    this.counter.destroy();
    this.text.destroy();
  }
}

Worth knowing: init() is safe to call more than once — it destroys any previous instance first — so re-initialising after an @Input change will not leave a stale observer behind.

Size.

10 KB gzipped for every API at once, and each one is a separate entry point — so a page that only reveals elements ships 3.9 KB, not the lot. The equivalent GSAP stack for the same work is 47.5 KB, which makes this 4.75× smaller. GSAP is free and considerably broader; if you need timelines, Draggable or Flip, use GSAP.

Measured 2026-08-14 at gzip level 9 against gsap 3.15.0 and svg-scroll-draw 2.10.0. Full comparison →

Angular questions.

How do I animate on scroll in Angular?

Import ScrollDrawRef from svg-scroll-draw/angular, create an instance as a component field, call init() with the native element in ngAfterViewInit, and call destroy() in ngOnDestroy. No NgModule registration and no Angular peer dependency are required.

Does svg-scroll-draw depend on @angular/core?

No. The Angular entry point exports framework-agnostic classes with no Angular import, so there is no peer-dependency version to match and the same code works in Angular 16 and later.

Why ngAfterViewInit rather than ngOnInit?

The element referenced by @ViewChild does not exist until the view has been initialised. Calling init() in ngOnInit would pass an undefined native element.