Плагин followCursor

Плагин followCursor в библиотеке Tippy.js позволяет привязывать всплывающую подсказку (tooltip) не к статичному элементу, а к текущему положению курсора. В отличие от стандартного поведения, при котором tooltip позиционируется относительно DOM-узла, здесь он динамически следует за указателем мыши.

Это поведение особенно полезно в случаях:

  • отображения вспомогательной информации в интерактивных графиках;
  • реализации кастомных подсказок в canvas/WebGL;
  • создания эффектов «живых» интерфейсов;
  • работы с плотными интерфейсами, где важно избегать перекрытия элементов.

Подключение плагина

Плагин не включён в базовую сборку автоматически и должен быть импортирован отдельно:

import tippy, {followCursor} from 'tippy.js';
import 'tippy.js/dist/tippy.css';

После импорта плагин необходимо зарегистрировать в настройках:

tippy(targets, {
  content: 'Подсказка',
  followCursor: true,
  plugins: [followCursor],
});

Ключевой момент: без указания plugins: [followCursor] параметр followCursor не будет работать.


Режимы работы followCursor

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

true

Tooltip следует за курсором по обеим осям:

followCursor: true

'horizontal'

Следование только по горизонтали:

followCursor: 'horizontal'

'vertical'

Следование только по вертикали:

followCursor: 'vertical'

'initial'

Tooltip позиционируется по координате курсора в момент появления, но не двигается далее:

followCursor: 'initial'

Этот режим полезен, если нужно избежать «дрожания» tooltip при движении мыши.


Взаимодействие с позиционированием

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

Под капотом происходит:

  • перехват события mousemove;
  • обновление виртуального reference;
  • пересчёт позиции через Popper.js.

Это означает:

  • увеличенную нагрузку при интенсивном движении мыши;
  • необходимость учитывать производительность.

Ограничение области отслеживания

По умолчанию tooltip следует за курсором только в пределах элемента, к которому он привязан. Однако можно изменить поведение, комбинируя с triggerTarget:

tippy(button, {
  content: 'Подсказка',
  followCursor: true,
  plugins: [followCursor],
  triggerTarget: document.body,
});

В этом случае отслеживание может происходить глобально.


Управление производительностью

Постоянное обновление позиции может создавать нагрузку, особенно при большом количестве tooltip-элементов.

Основные рекомендации:

1. Ограничение количества активных tooltip

tippy('.item', {
  followCursor: true,
  plugins: [followCursor],
  delay: [100, 0],
});

2. Использование debounce/throttle (кастомно) При необходимости можно обернуть обработку движения курсора:

let lastEvent;

document.addEventListener('mousemove', (event) => {
  lastEvent = event;
});

(реализация зависит от архитектуры приложения)

3. Использование режима 'initial' Минимизирует перерасчёты:

followCursor: 'initial'

Совместимость с другими опциями

interactive

При включённом interactive: true tooltip остаётся доступным для взаимодействия, но поведение с followCursor может быть неочевидным: курсор может «убегать» от tooltip.

interactive: true,
followCursor: true

Рекомендуется использовать аккуратно или избегать такой комбинации.


placement

Несмотря на динамическую позицию, placement всё ещё влияет на расположение относительно курсора:

placement: 'top'

Это означает, что tooltip будет находиться, например, выше курсора, а не перекрывать его.


offset

Позволяет сместить tooltip от курсора:

offset: [0, 10]

Полезно для:

  • предотвращения перекрытия указателя;
  • улучшения читаемости.

Работа с кастомным контентом

Плагин особенно эффективен в сочетании с динамическим контентом:

tippy(element, {
  content(reference) {
    return `Координаты: ${reference.dataset.x}, ${reference.dataset.y}`;
  },
  followCursor: true,
  plugins: [followCursor],
});

Можно обновлять содержимое на основе положения курсора или состояния приложения.


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

Так как canvas не содержит отдельных DOM-элементов, followCursor становится ключевым инструментом:

const tooltip = tippy(document.body, {
  content: '',
  followCursor: true,
  plugins: [followCursor],
  trigger: 'manual',
});

canvas.addEventListener('mousemove', (event) => {
  tooltip.setContent(`X: ${event.offsetX}, Y: ${event.offsetY}`);
  tooltip.show();
});

Здесь tooltip полностью управляется вручную.


Типичные ошибки

Отсутствие подключения плагина

// Ошибка
followCursor: true

// Правильно
plugins: [followCursor]

Неправильное ожидание поведения с interactive Tooltip может вести себя нестабильно при попытке взаимодействия.


Проблемы с мобильными устройствами Плагин ориентирован на мышь и не работает корректно с touch-событиями без дополнительной логики.


Расширенные сценарии

Имитация кастомного курсора

tippy(document.body, {
  content: 'Подсказка',
  followCursor: true,
  plugins: [followCursor],
  arrow: false,
});

Можно стилизовать tooltip как курсор.


Комбинация с delay

delay: [200, 0],
followCursor: true

Позволяет избежать мгновенного появления при случайных движениях мыши.


Условная активация

tippy(elements, {
  followCursor: window.innerWidth > 768,
  plugins: [followCursor],
});

Полезно для адаптивных интерфейсов.


Внутренний механизм работы

Плагин создаёт виртуальный reference-элемент со следующими характеристиками:

  • отсутствует в DOM;
  • имеет метод getBoundingClientRect;
  • возвращает координаты курсора.

При каждом событии mousemove:

  1. обновляются координаты;
  2. вызывается обновление Popper-инстанса;
  3. tooltip перерисовывается.

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


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

  • использовать offset для предотвращения перекрытия курсора;
  • избегать одновременного использования с interactive, если не требуется;
  • применять 'initial' для снижения нагрузки;
  • не использовать на мобильных устройствах без fallback-логики;
  • ограничивать область применения при большом количестве элементов.