Использование в Angular

Для работы с ScrollMagic в Angular необходимо сначала установить библиотеку через npm:

npm install scrollmagic
npm install @types/scrollmagic --save-dev

@types/scrollmagic добавляет поддержку TypeScript, что особенно важно для Angular-проектов. После установки библиотеку можно импортировать в компонент или сервис:

import * as ScrollMagic from 'scrollmagic';

Если требуется интеграция с анимациями через GSAP, дополнительно нужно установить:

npm install gsap

и подключить плагины через:

import { gsap } from 'gsap';
import { ScrollMagicPluginGsap } from 'scrollmagic-plugin-gsap';
ScrollMagicPluginGsap(ScrollMagic, gsap);

Создание контроллера ScrollMagic

В Angular лучше создавать экземпляр контроллера внутри ngAfterViewInit, чтобы убедиться, что DOM полностью загружен:

import { Component, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-scroll-example',
  templateUrl: './scroll-example.component.html',
  styleUrls: ['./scroll-example.component.scss']
})
export class ScrollExampleComponent implements AfterViewInit {

  private controller: ScrollMagic.Controller;

  ngAfterViewInit() {
    this.controller = new ScrollMagic.Controller();
  }
}

Контроллер управляет всеми сценами (Scene) на странице и обеспечивает их синхронизацию с прокруткой.

Создание сцен (Scene)

Сцена определяет, какой элемент и когда должен анимироваться. В Angular это делается внутри ngAfterViewInit:

import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
import * as ScrollMagic from 'scrollmagic';
import { gsap } from 'gsap';
import { ScrollMagicPluginGsap } from 'scrollmagic-plugin-gsap';
ScrollMagicPluginGsap(ScrollMagic, gsap);

@Component({
  selector: 'app-scroll-animation',
  template: `<div #box class="box"></div>`,
  styles: [`.box { width: 100px; height: 100px; background-color: red; margin-top: 200px; }`]
})
export class ScrollAnimationComponent implements AfterViewInit {

  @ViewChild('box') box: ElementRef;
  private controller: ScrollMagic.Controller;

  ngAfterViewInit() {
    this.controller = new ScrollMagic.Controller();

    const scene = new ScrollMagic.Scene({
      triggerElement: this.box.nativeElement,
      duration: 300,
      triggerHook: 0.5
    })
    .setTween(gsap.to(this.box.nativeElement, { x: 300 }))
    .addTo(this.controller);
  }
}

Ключевые параметры Scene:

  • triggerElement – элемент, при достижении которого начинается анимация.
  • duration – длительность сцены в пикселях прокрутки.
  • triggerHook – точка срабатывания сцены (от 0 – верх экрана до 1 – низ экрана).

Использование ViewChild и Angular подхода

Angular строго разделяет логику и шаблон, поэтому взаимодействие с DOM через ScrollMagic осуществляется через @ViewChild. Это позволяет безопасно ссылаться на элементы после их рендеринга, избегая ошибок в момент инициализации компонента.

Если необходимо создать несколько сцен для коллекции элементов, удобно использовать QueryList и ViewChildren:

import { ViewChildren, QueryList } from '@angular/core';

@ViewChildren('boxes') boxes: QueryList<ElementRef>;

ngAfterViewInit() {
  this.controller = new ScrollMagic.Controller();
  
  this.boxes.forEach(box => {
    new ScrollMagic.Scene({
      triggerElement: box.nativeElement,
      triggerHook: 0.8
    })
    .setClassToggle(box.nativeElement, 'visible')
    .addTo(this.controller);
  });
}

Очистка ресурсов

Angular активно использует жизненный цикл компонентов, поэтому крайне важно отключать контроллеры и сцены при уничтожении компонента, чтобы избежать утечек памяти:

import { OnDestroy } from '@angular/core';

export class ScrollAnimationComponent implements AfterViewInit, OnDestroy {
  private controller: ScrollMagic.Controller;

  ngAfterViewInit() {
    this.controller = new ScrollMagic.Controller();
  }

  ngOnDestroy() {
    if (this.controller) {
      this.controller.destroy(true);
      this.controller = null;
    }
  }
}

Метод destroy(true) удаляет все сцены и слушатели событий, освобождая ресурсы.

Анимации с GSAP и ScrollMagic

ScrollMagic отлично интегрируется с GSAP для плавных анимаций. Можно задавать сложные последовательности через TimelineLite или TimelineMax:

const timeline = gsap.timeline();
timeline.to(this.box.nativeElement, { x: 200, duration: 1 });
timeline.to(this.box.nativeElement, { y: 100, duration: 1 });

new ScrollMagic.Scene({
  triggerElement: this.box.nativeElement,
  duration: 500,
})
.setTween(timeline)
.addTo(this.controller);

Такой подход позволяет составлять сложные цепочки анимаций, синхронизированные с прокруткой, без дублирования кода.

Адаптивность и динамические элементы

В Angular часто элементы генерируются динамически через *ngFor. В таких случаях ScrollMagic сцены создаются после полной отрисовки списка, используя ngAfterViewInit и подписку на changes в QueryList:

this.boxes.changes.subscribe((boxes: QueryList<ElementRef>) => {
  boxes.forEach(box => {
    new ScrollMagic.Scene({ triggerElement: box.nativeElement })
      .setClassToggle(box.nativeElement, 'active')
      .addTo(this.controller);
  });
});

Это гарантирует, что анимации применяются ко всем элементам, даже если они появляются динамически.

Взаимодействие с Angular Router

При навигации между страницами через Router, важно инициализировать ScrollMagic на новых компонентах и очищать контроллеры на старых. Можно использовать NavigationEnd событие:

import { Router, NavigationEnd } from '@angular/router';

constructor(private router: Router) {
  this.router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {
      // инициализация ScrollMagic для текущего компонента
    }
  });
}

Это предотвращает пересечение сцен и сохраняет производительность при одностраничных приложениях.


Этот подход обеспечивает полноценную интеграцию ScrollMagic в Angular, позволяя создавать гибкие, динамичные и производительные анимации, синхронизированные с прокруткой, с соблюдением всех стандартов Angular и безопасного управления DOM.