Виртуальные элементы

Tippy.js поддерживает работу с виртуальными элементами, что позволяет создавать тултипы и всплывающие подсказки не только для обычных DOM-узлов, но и для объектов, которые не присутствуют напрямую в DOM. Это особенно полезно для динамических интерфейсов, кастомных canvas-рендеров или интерактивных SVG-графиков, где стандартный DOM-селектор использовать невозможно.

Основная идея

Виртуальный элемент в Tippy.js представляет собой объект с двумя обязательными свойствами:

const virtualElement = {
  getBoundingClientRect: () => DOMRect,
  clientWidth: number,
  clientHeight: number
};
  • getBoundingClientRect — функция, возвращающая объект DOMRect, описывающий позицию и размеры виртуального элемента.
  • clientWidth и clientHeight — числовые значения ширины и высоты элемента.

Эти свойства позволяют Tippy.js рассчитывать позицию тултипа точно так же, как для обычного DOM-элемента.

Создание виртуального элемента

Простейший пример создания виртуального элемента для тултипа:

const virtualButton = {
  getBoundingClientRect: () => ({
    top: 100,
    left: 200,
    right: 250,
    bottom: 130,
    width: 50,
    height: 30
  }),
  clientWidth: 50,
  clientHeight: 30
};

tippy(virtualButton, {
  content: 'Тултип для виртуального элемента',
  placement: 'right'
});

В этом примере тултип будет отображаться в позиции, заданной вручную через координаты top, left, width и height.

Интеграция с динамическими интерфейсами

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

let mouseX = 0;
let mouseY = 0;

document.addEventListener('mousemove', (e) => {
  mouseX = e.clientX;
  mouseY = e.clientY;
});

const virtualCursor = {
  getBoundingClientRect: () => ({
    top: mouseY,
    left: mouseX,
    right: mouseX,
    bottom: mouseY,
    width: 0,
    height: 0
  }),
  clientWidth: 0,
  clientHeight: 0
};

tippy(virtualCursor, {
  content: 'Следящий за курсором тултип',
  placement: 'top',
  followCursor: true
});

Здесь тултип привязан к позиции курсора мыши, даже если самого элемента в DOM нет. Благодаря followCursor: true Tippy.js корректно отслеживает перемещение.

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

SVG-элементы и canvas-графика часто не имеют стандартных размеров для прямого привязывания тултипов. Виртуальные элементы решают эту проблему:

const svgPoint = { x: 150, y: 75 };

const virtualSVGElement = {
  getBoundingClientRect: () => ({
    top: svgPoint.y,
    left: svgPoint.x,
    right: svgPoint.x,
    bottom: svgPoint.y,
    width: 0,
    height: 0
  }),
  clientWidth: 0,
  clientHeight: 0
};

tippy(virtualSVGElement, {
  content: 'Информация о точке на SVG',
  placement: 'bottom'
});

Таким образом можно создавать интерактивные подсказки для отдельных точек графика или элементов SVG без создания лишних DOM-узлов.

Адаптация при изменении размеров окна

Поскольку виртуальные элементы не связаны напрямую с DOM, необходимо обновлять позицию при изменении размеров окна или контейнера:

window.addEventListener('resize', () => {
  tippyInstance.popperInstance.update();
});

Метод update() заставляет Tippy.js пересчитать позицию тултипа, используя текущие координаты виртуального элемента.

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

  • Для часто обновляемых элементов использовать debounce или requestAnimationFrame, чтобы избежать лишних перерасчетов.
  • Минимизировать сложность функции getBoundingClientRect, так как она вызывается при каждом рендере тултипа.
  • Если элемент имеет фиксированную позицию, заранее вычислять координаты и не пересчитывать на каждом кадре.

Полезные свойства и методы

  • tippy.show() и tippy.hide() работают с виртуальными элементами точно так же, как с DOM-узлами.
  • tippy.setProps({ content: 'новый контент' }) позволяет динамически менять содержимое тултипа.
  • tippy.popperInstance предоставляет доступ к Popper.js-инстансу для тонкой настройки позиционирования.

Практическое применение

  • Визуализация данных на canvas: тултипы для отдельных точек графика или столбцов диаграммы.
  • SVG-карты и интерактивные схемы: подсказки для координат и объектов.
  • Динамически создаваемые интерфейсные элементы: кнопки, меню, элементы списка, которых нет в момент инициализации страницы.
  • “Следящие” тултипы: тултип, который перемещается вместе с курсором или другим объектом.

Виртуальные элементы делают Tippy.js универсальным инструментом для интерактивных и нестандартных интерфейсов, расширяя возможности стандартного DOM-позиционирования. Их гибкость позволяет создавать сложные и динамичные UI-сценарии без необходимости создавать лишние элементы в HTML.