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

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

npm install @floating-ui/dom

После установки важно импортировать необходимые функции из пакета:

import { computePosition, offset, flip, shift, autoUpdate } from '@floating-ui/dom';

Эти функции позволяют вычислять позиционирование всплывающих элементов и динамически их корректировать в зависимости от положения целевого элемента и доступного пространства.


Базовое позиционирование

В Angular-компоненте создаются два ключевых элемента: reference (ссылка, к которой привязывается всплывающий элемент) и floating (сам всплывающий элемент). Например:

@Component({
  selector: 'app-tooltip',
  template: `
    
    
Подсказка
`, styles: [` .tooltip { position: absolute; background: #333; color: #fff; padding: 5px 10px; border-radius: 4px; display: none; } `] }) export class TooltipComponent implements AfterViewInit, OnDestroy { @ViewChild('button') button!: ElementRef; @ViewChild('tooltip') tooltip!: ElementRef; private cleanup?: () => void; ngAfterViewInit() { this.cleanup = autoUpdate( this.button.nativeElement, this.tooltip.nativeElement, () => this.updatePosition() ); this.button.nativeElement.addEventListener('mouseenter', () => { this.tooltip.nativeElement.style.display = 'block'; }); this.button.nativeElement.addEventListener('mouseleave', () => { this.tooltip.nativeElement.style.display = 'none'; }); } updatePosition() { computePosition(this.button.nativeElement, this.tooltip.nativeElement, { placement: 'top', middleware: [offset(8), flip(), shift({ padding: 5 })] }).then(({ x, y }) => { Object.assign(this.tooltip.nativeElement.style, { left: `${x}px`, top: `${y}px` }); }); } ngOnDestroy() { this.cleanup?.(); } }

Ключевые моменты:

  • computePosition — вычисляет координаты всплывающего элемента.
  • offset — задаёт расстояние между reference и floating элементом.
  • flip — автоматически меняет сторону, если элемент не помещается.
  • shift — корректирует позицию, чтобы элемент оставался в видимой области.
  • autoUpdate — подписывает floating элемент на изменения размеров и скролла, чтобы позиция оставалась актуальной.

Использование в реактивных формах и динамических компонентах

В Angular часто встречаются динамические элементы, например, меню автодополнения. Для корректного позиционирования Floating UI можно использовать ngAfterViewChecked, чтобы гарантировать, что элементы уже рендерятся перед вызовом computePosition.

ngAfterViewChecked() {
  if (this.isDropdownVisible) {
    this.updatePosition();
  }
}

Также важно корректно очищать подписки, чтобы избежать утечек памяти:

ngOnDestroy() {
  this.cleanup?.();
}

Работа с Angular CDK Overlay

Для интеграции Floating UI с Angular CDK Overlay можно использовать кастомные стратегии позиционирования:

import { ConnectedPosition, Overlay, OverlayRef } from '@angular/cdk/overlay';

const overlayRef: OverlayRef = this.overlay.create({
  positionStrategy: this.overlay.position()
    .flexibleConnectedTo(this.button)
    .withPositions([{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' }])
});

Однако Floating UI обеспечивает более гибкое управление поведением middleware, что особенно полезно при создании сложных всплывающих компонентов с динамическим содержимым.


Middleware Floating UI в Angular

1. offset() — отступы между элементами:

offset(10) // 10 пикселей от reference

2. flip() — автоматический поворот, если элемент выходит за границы viewport:

flip({ fallbackPlacements: ['bottom', 'right'] })

3. shift() — подстраивание позиции под границы экрана:

shift({ padding: 5 })

4. arrow() — позиционирование стрелки подсказки:

import { arrow } from '@floating-ui/dom';

arrow({ element: arrowElement })

В Angular можно обновлять координаты стрелки аналогично обновлению позиции floating элемента.


Адаптация под рендеринг в Shadow DOM

Если Angular-компонент использует ViewEncapsulation.ShadowDom, Floating UI автоматически поддерживает расчёт позиции через computePosition, но важно указывать правильный контейнер для autoUpdate, чтобы слушатели скролла и resize работали корректно.

autoUpdate(
  this.button.nativeElement,
  this.tooltip.nativeElement,
  () => this.updatePosition(),
  { ancestorScroll: true }
);

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

  • Throttle обновления: если позиция обновляется часто (scroll, resize), можно использовать requestAnimationFrame или RxJS auditTime.
  • Lazy инициализация: floating элементы не нужно создавать до момента взаимодействия пользователя.
  • Разделение middleware: используйте только необходимые, чтобы уменьшить вычислительную нагрузку.

Совместимость с Angular Animations

Floating UI легко интегрируется с @angular/animations. Например, анимация появления tooltip:

animations: [
  trigger('tooltipFade', [
    state('hidden', style({ opacity: 0 })),
    state('visible', style({ opacity: 1 })),
    transition('hidden => visible', animate('150ms ease-in')),
    transition('visible => hidden', animate('100ms ease-out')),
  ])
]

Применение состояния может быть синхронизировано с показом tooltip и позиционированием через Floating UI.