Тултипы для canvas

Tooltipster — мощная библиотека для создания кастомных тултипов на веб-страницах. Работа с элементами <canvas> имеет свои особенности, так как у этих элементов отсутствует стандартная DOM-структура для внутренних объектов. Для корректного отображения тултипов необходимо учитывать координаты мыши относительно канваса и динамически вычислять позицию всплывающих подсказок.

Привязка тултипа к canvas

Элементы <canvas> не имеют дочерних элементов DOM, поэтому стандартный вызов $('.element').tooltipster() не применим к отдельным объектам внутри канваса. Решение заключается в отслеживании событий мыши (mousemove, mouseover, mouseout) и программной активации тултипа через API Tooltipster:

const canvas = document.getElementById('myCanvas');
const tooltip = $('<div>Tooltip Content</div>').tooltipster({
    theme: 'tooltipster-light',
    animation: 'fade',
    delay: 100,
    trigger: 'custom',
    interactive: true
}).tooltipster('instance');

canvas.addEventListener('mousemove', (event) => {
    const rect = canvas.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;

    if (isPointInShape(x, y)) { // Функция проверяет попадание курсора в фигуру
        tooltip.open(event.currentTarget, {
            content: 'Описание объекта'
        });
    } else {
        tooltip.close();
    }
});

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

  • trigger: 'custom' — позволяет управлять открытием тултипа вручную.
  • interactive: true — делает тултип кликабельным, что важно для сложных интерфейсов.
  • getBoundingClientRect() — используется для перевода координат мыши в координаты канваса.

Динамический контент и обновление тултипа

Tooltipster позволяет менять содержимое тултипа в процессе работы. Для <canvas> это особенно полезно, когда нужно отображать информацию о текущем объекте под курсором.

function updateTooltipContent(x, y) {
    const shapeInfo = getShapeInfoAt(x, y); // Возвращает данные о фигуре под курсором
    tooltip.content(shapeInfo ? `Тип: ${shapeInfo.type}, ID: ${shapeInfo.id}` : '');
}
  • tooltip.content() автоматически обновляет содержимое без необходимости закрывать тултип.
  • Рекомендуется использовать дебаунсинг для вызова обновления, чтобы не перегружать интерфейс событиями mousemove.

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

Tooltipster умеет автоматически корректировать позицию тултипа, чтобы он не выходил за пределы окна. Для элементов <canvas> полезно учитывать смещение канваса относительно окна:

tooltip.open(event.currentTarget, {
    content: 'Описание объекта',
    functionPosition: function(instance, helper, position){
        const canvasRect = canvas.getBoundingClientRect();
        position.coord.left += canvasRect.left;
        position.coord.top += canvasRect.top;
        return position;
    }
});
  • functionPosition позволяет вручную корректировать позицию тултипа, учитывая границы и смещение канваса.
  • Можно комбинировать с логикой, которая перемещает тултип в зависимости от границ окна (position.side и position.coord).

Стилизация тултипов для canvas

Для интерактивных канвасов важно, чтобы тултипы были минимально навязчивыми и визуально интегрированными. Tooltipster поддерживает кастомные темы и CSS-анимации:

.tooltipster-light {
    background: rgba(0,0,0,0.8);
    color: #fff;
    font-size: 14px;
    border-radius: 4px;
    padding: 8px 12px;
    max-width: 250px;
}
  • Использование прозрачного фона помогает сохранить видимость содержимого канваса.
  • Ограничение ширины предотвращает перекрытие важных областей интерфейса.

Обработка сложных объектов и графиков

Для графиков, диаграмм и интерактивных схем внутри <canvas> полезно создавать карту объектов. Каждому объекту присваивается область координат, по которой можно определить попадание курсора:

function isPointInShape(x, y) {
    return shapes.some(shape => (
        x >= shape.x && x <= shape.x + shape.width &&
        y >= shape.y && y <= shape.y + shape.height
    ));
}
  • Список shapes может содержать прямоугольники, круги или сложные полигоны.
  • Проверка попадания позволяет динамически отображать тултипы только для активных объектов.

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

Большие <canvas> с множеством объектов могут вызвать падение FPS при частых событиях mousemove. Для минимизации нагрузки:

  1. Использовать дебаунсинг обновления тултипа.
  2. Предварительно вычислять области объектов, а не рассчитывать их на каждом движении мыши.
  3. Использовать requestAnimationFrame для синхронизации событий с перерисовкой канваса.

Пример комплексной интеграции

canvas.addEventListener('mousemove', (event) => {
    requestAnimationFrame(() => {
        const rect = canvas.getBoundingClientRect();
        const x = event.clientX - rect.left;
        const y = event.clientY - rect.top;

        const shape = getShapeAt(x, y);
        if(shape){
            tooltip.content(`Объект: ${shape.name}`);
            tooltip.open(canvas, { side: 'top' });
        } else {
            tooltip.close();
        }
    });
});

Такой подход обеспечивает плавное отображение тултипов для любых интерактивных элементов внутри <canvas>.

Tooltipster позволяет создавать сложные интерактивные подсказки, контролируя их позицию, содержимое и стиль, что делает его идеальным инструментом для динамических канвасов и визуализаций.