Методы platform объекта

Объект platform в библиотеке Floating UI — это абстрактный слой, отвечающий за получение геометрических и средовых данных. Он изолирует алгоритмы позиционирования от конкретной среды выполнения: браузера, React Native, Canvas или даже пользовательских рендереров.

Алгоритмы вычисления позиции (computePosition) не работают напрямую с DOM. Вместо этого они вызывают методы platform, которые предоставляют всю необходимую информацию:

  • размеры элементов
  • положение вьюпорта
  • прокрутку
  • масштабирование
  • clipping-контейнеры

Это делает систему расширяемой и переносимой.


Общая структура platform

Объект platform представляет собой набор функций:

const platform = {
  getElementRects,
  getClippingRect,
  getDimensions,
  getOffsetParent,
  getDocumentElement,
  getScale,
  isElement,
  isRTL
};

Каждый метод выполняет строго определённую роль. Алгоритмы позиционирования полагаются на эти методы как на источник истины.


getElementRects

Один из ключевых методов. Возвращает прямоугольники (rects) для reference и floating элементов.

const rects = await platform.getElementRects({
  reference,
  floating,
  strategy
});

Структура результата:

{
  reference: { x, y, width, height },
  floating: { x, y, width, height }
}

Особенности:

  • координаты reference обычно вычисляются относительно viewport
  • floating — относительно offset parent
  • учитывается стратегия позиционирования (absolute или fixed)

Этот метод критичен для начального расчёта позиции.


getClippingRect

Возвращает область, в пределах которой элемент может быть видим.

const clippingRect = await platform.getClippingRect({
  element,
  boundary,
  rootBoundary,
  strategy
});

Назначение:

  • определяет границы для middleware вроде flip и shift

  • учитывает:

    • overflow контейнеры
    • viewport
    • document

Параметры:

  • boundary — список контейнеров или clippingAncestors
  • rootBoundary — обычно viewport или document

Важно:

Если clipping рассчитан неверно — позиционирование будет ломаться при прокрутке и переполнении.


getDimensions

Возвращает размеры элемента.

const dimensions = await platform.getDimensions(element);

Результат:

{
  width: number,
  height: number
}

Отличие от getBoundingClientRect:

  • не содержит координат
  • может учитывать трансформации и особенности среды

Используется при вычислении размеров floating-элемента, особенно до его отображения.


getOffsetParent

Определяет offset-контекст для элемента.

const offsetParent = await platform.getOffsetParent(element);

Что возвращает:

  • ближайший позиционированный предок
  • или window / documentElement

Зачем нужен:

  • корректное вычисление координат для absolute
  • учёт вложенных контекстов позиционирования

Сложности:

  • position: fixed игнорирует offset parent
  • трансформации (transform) создают новые контексты

getDocumentElement

Возвращает корневой элемент документа.

const docEl = platform.getDocumentElement(element);

Обычно это:

document.documentElement

Используется для:

  • вычисления размеров страницы
  • работы с rootBoundary: document

getScale

Определяет масштаб элемента.

const scale = await platform.getScale(element);

Результат:

{
  x: number,
  y: number
}

Причины появления масштаба:

  • CSS transform: scale(...)
  • zoom браузера
  • вложенные трансформации

Зачем нужен:

Без учёта масштаба координаты будут искажены.


isElement

Проверяет, является ли объект элементом.

platform.isElement(value);

Возвращает:

true | false

Используется внутри алгоритмов для ветвления логики:

  • DOM элемент
  • виртуальный элемент
  • кастомный объект

isRTL

Определяет направление текста.

const rtl = await platform.isRTL(element);

Возвращает:

true // если right-to-left
false // если left-to-right

Влияние:

  • смещение по оси X меняется
  • middleware (например offset) работает иначе

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

Методы platform не используются изолированно. Они образуют цепочку:

  1. getElementRects — базовая геометрия
  2. getOffsetParent — контекст координат
  3. getScale — корректировка размеров
  4. getClippingRect — ограничения
  5. middleware применяют изменения

Кастомизация platform

Floating UI позволяет полностью заменить platform.

Пример:

const customPlatform = {
  ...platform,
  getDimensions: async (element) => {
    return {
      width: element.customWidth,
      height: element.customHeight
    };
  }
};

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

computePosition(reference, floating, {
  platform: customPlatform
});

Применение вне DOM

platform позволяет использовать Floating UI:

  • в Canvas
  • в WebGL
  • в мобильных средах
  • в headless UI системах

Пример виртуального элемента:

const virtualElement = {
  getBoundingClientRect() {
    return {
      x: 100,
      y: 200,
      width: 0,
      height: 0
    };
  }
};

В этом случае platform должен уметь работать без DOM API.


Асинхронность методов

Все методы могут быть асинхронными:

await platform.getElementRects(...)

Это важно для:

  • React Native
  • удалённых вычислений
  • сложных layout-систем

Ошибки и пограничные случаи

1. Неверный offset parent

Приводит к смещению floating-элемента.

2. Игнорирование scale

Особенно заметно при zoom и transform.

3. Неправильный clipping

Элемент может “вылезать” за границы.

4. Несоответствие coordinate space

Разные системы координат ломают расчёты.


Минимальная реализация platform

const minimalPlatform = {
  getElementRects: async ({reference, floating}) => ({
    reference: reference.getBoundingClientRect(),
    floating: floating.getBoundingClientRect()
  }),
  getDimensions: async (el) => ({
    width: el.offsetWidth,
    height: el.offsetHeight
  }),
  getOffsetParent: async () => window,
  getDocumentElement: () => document.documentElement,
  getScale: async () => ({x: 1, y: 1}),
  isElement: (value) => value instanceof Element,
  isRTL: async () => false,
  getClippingRect: async () => ({
    x: 0,
    y: 0,
    width: window.innerWidth,
    height: window.innerHeight
  })
};

Роль platform в middleware

Middleware (flip, shift, offset, arrow) активно используют platform:

  • detectOverflow вызывает getClippingRect
  • arrow использует getDimensions
  • shift зависит от координат rect

Таким образом, platform — это фундамент всей системы позиционирования.


Расширяемость и тестируемость

Разделение логики и платформы даёт преимущества:

  • тестирование без DOM
  • мокирование методов
  • независимость от браузера
  • переносимость алгоритмов

Это один из ключевых архитектурных элементов Floating UI.