Для работы с 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);
В 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) на странице и
обеспечивает их синхронизацию с прокруткой.
Сцена определяет, какой элемент и когда должен
анимироваться. В 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) удаляет все сцены и слушатели
событий, освобождая ресурсы.
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);
});
});
Это гарантирует, что анимации применяются ко всем элементам, даже если они появляются динамически.
При навигации между страницами через 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.