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

Waypoints — это лёгкая библиотека для отслеживания прокрутки страницы и выполнения функций при достижении определённых элементов. В Angular она используется для создания динамических эффектов при скролле, ленивой подгрузки контента, анимаций и других интерактивных сценариев. Основная задача — корректная интеграция сторонней библиотеки с жизненным циклом компонентов Angular.


Установка и подключение

Waypoints можно установить через npm:

npm install waypoints

После установки подключение в Angular осуществляется через импорт в компонент или сервис:

import * as Waypoint from 'waypoints/lib/noframework.waypoints';

Важно использовать вариант noframework, так как Angular не требует jQuery для работы Waypoints.


Создание директивы для Waypoints

Для удобного применения в Angular оптимально создавать собственную директиву, которая будет управлять жизненным циклом Waypoints:

import { Directive, ElementRef, Input, OnDestroy, AfterViewInit } from '@angular/core';
import * as Waypoint from 'waypoints/lib/noframework.waypoints';

@Directive({
  selector: '[appWaypoint]'
})
export class WaypointDirective implements AfterViewInit, OnDestroy {
  @Input() offset: string | number = '50%';
  @Input() onEnter: () => void = () => {};

  private waypoint!: Waypoint;

  constructor(private el: ElementRef) {}

  ngAfterViewInit() {
    this.waypoint = new Waypoint({
      element: this.el.nativeElement,
      handler: () => this.onEnter(),
      offset: this.offset
    });
  }

  ngOnDestroy() {
    if (this.waypoint) {
      this.waypoint.destroy();
    }
  }
}

Пояснения:

  • AfterViewInit используется для того, чтобы элемент уже присутствовал в DOM, что критично для Waypoints.
  • OnDestroy позволяет корректно удалять экземпляр Waypoint и предотвращать утечки памяти.
  • offset задаёт смещение точки активации относительно верхнего края окна.

Использование директивы в шаблоне

<div *ngFor="let section of sections" 
     appWaypoint 
     [offset]="'75%'" 
     [onEnter]="() => handleEnter(section)">
  {{ section.title }}
</div>

Здесь каждая секция отслеживается отдельно. При достижении точки активации вызывается функция handleEnter, переданная через Input.


Управление прокруткой и анимацией

Waypoints в Angular часто используется вместе с Angular анимациями:

handleEnter(section: any) {
  section.active = true; // Используется для добавления класса анимации
}

В шаблоне:

<div [@fadeIn]="section.active ? 'visible' : 'hidden'">
  {{ section.content }}
</div>

Это позволяет создавать плавные анимации появления контента при скролле без прямого вмешательства в DOM.


Поддержка динамического контента

Для динамически загружаемых элементов важно пересоздавать Waypoints после изменения DOM. В Angular это реализуется через ngAfterViewChecked:

ngAfterViewChecked() {
  this.waypoints.forEach(wp => wp.destroy());
  this.initializeWaypoints();
}

private initializeWaypoints() {
  this.sections.forEach(section => {
    const wp = new Waypoint({
      element: document.getElementById(section.id),
      handler: () => this.handleEnter(section),
      offset: '75%'
    });
    this.waypoints.push(wp);
  });
}

Такой подход гарантирует корректную работу с контентом, который загружается асинхронно, например через HTTP-запросы.


Использование с виртуальным скроллом

При применении Angular CDK Virtual Scroll необходимо учитывать, что элементы не всегда присутствуют в DOM. В этом случае Waypoints создаётся только для видимых элементов и пересоздаётся при скролле:

cdkVirtualFor="let item of items; let i = index" 
(appWaypoint)="onEnter(item)">

Каждое событие прокрутки обрабатывается индивидуально, а Waypoints активируется при появлении элемента в видимой области.


Настройка глобальных событий

Waypoints поддерживает привязку к окну (window) для обработки событий скролла глобально:

new Waypoint({
  element: document.body,
  handler: () => console.log('Scrolled to body'),
  offset: '100%'
});

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


Производительность и оптимизация

  • Не создавать слишком много Waypoints на странице, особенно для длинных списков.
  • Использовать делегирование или директивы для повторяющихся элементов.
  • Уничтожать Waypoints при уничтожении компонента для предотвращения утечек памяти.
  • Для больших страниц оптимально использовать requestAnimationFrame или IntersectionObserver вместе с Waypoints для снижения нагрузки на скролл.

Waypoints в Angular позволяет гибко управлять скроллом и событиями появления элементов, интегрируясь с шаблонами, директивами и анимациями. Использование директив и сервисов обеспечивает чистую архитектуру и соответствие принципам Angular.