Форматирование данных в tooltip

В Kepler.gl всплывающие подсказки (tooltip) формируются на основе данных слоя и конфигурации визуализации. Tooltip не является отдельным UI-компонентом, который полностью контролируется разработчиком — он собирается динамически из описания слоя, полей данных и правил форматирования, заданных в visState.

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

Источник данных для tooltip

Основой tooltip является объект данных слоя (layer.data) и выбранная строка (feature), на которую пользователь навёл курсор.

Каждый слой в Kepler.gl работает с набором данных в формате:

{
  fields: [
    { name: 'timestamp', type: 'integer' },
    { name: 'lat', type: 'real' },
    { name: 'lng', type: 'real' }
  ],
  rows: [
    { timestamp: 1700000000, lat: 50.45, lng: 30.52 }
  ]
}

При наведении курсора Kepler.gl определяет активный объект и передаёт его в систему tooltip как “picked object”.

Формирование базового tooltip объекта

Когда пользователь взаимодействует с картой, формируется структура:

{
  layer: 'trip-layer',
  object: {
    index: 0,
    lat: 50.45,
    lng: 30.52,
    timestamp: 1700000000
  },
  fields: [
    'timestamp',
    'lat',
    'lng'
  ]
}

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

Роль visState в управлении tooltip

Основная логика управления tooltip находится в visState.interactionConfig.tooltip.

Пример конфигурации:

const config = {
  visState: {
    interactionConfig: {
      tooltip: {
        enabled: true,
        fieldsToShow: {
          'trip-layer': ['timestamp', 'lat', 'lng']
        },
        compareMode: false,
        compareType: 'absolute'
      }
    }
  }
};

fieldsToShow

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

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

  • можно задавать разные поля для разных слоёв
  • порядок полей влияет на порядок отображения
  • отсутствие слоя в конфигурации означает показ всех доступных полей

Преобразование значений через форматтеры колонок

Kepler.gl поддерживает форматирование значений через columnFormat. Это позволяет преобразовать сырые данные перед отображением в tooltip.

const config = {
  visState: {
    layers: [],
    interactionConfig: {},
    columnFormat: {
      timestamp: {
        format: 'YYYY-MM-DD HH:mm:ss'
      },
      lat: {
        format: 'latlng'
      }
    }
  }
};

Типы форматирования

Форматтеры применяются в зависимости от типа данных:

Числовые значения

  • округление
  • добавление разделителей
  • кастомные функции форматирования

Дата и время

  • преобразование UNIX timestamp
  • поддержка moment.js-подобных форматов

Географические координаты

  • форматирование в градусы
  • отображение в виде пары lat/lng

Порядок обработки данных перед tooltip

Перед отображением tooltip проходит следующий pipeline:

  1. Получение объекта из слоя
  2. Определение полей через fieldsToShow
  3. Применение columnFormat
  4. Приведение типов (если необходимо)
  5. Формирование финального массива ключ-значение

Пример результата после обработки:

[
  { name: 'timestamp', value: '2023-11-14 12:30:00' },
  { name: 'lat', value: '50.45°' },
  { name: 'lng', value: '30.52°' }
]

Кастомизация tooltip через getTooltip

Kepler.gl позволяет полностью переопределить содержимое tooltip через кастомную функцию.

const getTooltip = (hoveredObject) => {
  const { object, layer } = hoveredObject;

  return {
    title: `Объект слоя ${layer.id}`,
    fields: [
      {
        label: 'Время события',
        value: new Date(object.timestamp * 1000).toLocaleString()
      },
      {
        label: 'Координаты',
        value: `${object.lat}, ${object.lng}`
      }
    ]
  };
};

Такая функция позволяет:

  • объединять поля в логические группы
  • добавлять вычисляемые значения
  • скрывать часть исходных данных
  • форматировать значения независимо от глобальных настроек

Tooltip в различных типах слоёв

Разные типы слоёв Kepler.gl используют разные стратегии формирования tooltip.

PointLayer

Отображает свойства точки:

  • координаты
  • атрибуты объекта
  • данные из CSV/GeoJSON

ArcLayer

Tooltip содержит:

  • начальную и конечную точку
  • расстояние (если вычислено)
  • дополнительные поля маршрута

LineLayer

Основной акцент на:

  • геометрии линии
  • временных данных (если есть)
  • метаданных сегмента

HexagonLayer

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

  • агрегированные значения
  • статистика ячейки
  • количество объектов в ячейке

В этом случае tooltip чаще всего работает с агрегированными данными, а не с исходными строками.

Агрегация данных и её влияние на tooltip

При использовании агрегирующих слоёв (HexagonLayer, GridLayer) tooltip получает не исходные записи, а вычисленные значения.

Пример:

{
  count: 42,
  sum: 1200,
  avg: 28.5
}

В конфигурации можно управлять тем, какие агрегаты отображаются:

fieldsToShow: {
  'hex-layer': ['count', 'avg']
}

Форматирование вычисляемых полей

Часто tooltip содержит не только данные из набора, но и вычисляемые значения:

const enhancedObject = {
  ...object,
  speed: object.distance / object.time,
  efficiency: object.output / object.input
};

Для таких полей применяются те же правила columnFormat, однако важно учитывать:

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

Управление порядком и отображением полей

Порядок отображения tooltip определяется следующими факторами:

  1. порядок в fieldsToShow
  2. порядок полей в data schema
  3. порядок, возвращённый кастомным tooltip-функционалом

Пример строгого контроля порядка:

fieldsToShow: {
  'layer-id': ['name', 'category', 'value']
}

Условное отображение полей

В продвинутых сценариях tooltip может менять содержимое в зависимости от данных:

const getTooltip = ({ object }) => {
  const fields = [];

  if (object.type === 'vehicle') {
    fields.push({ label: 'Скорость', value: object.speed });
  }

  if (object.type === 'station') {
    fields.push({ label: 'Пассажиры', value: object.passengers });
  }

  return { fields };
};

Такой подход позволяет создавать адаптивные tooltip-структуры, зависящие от бизнес-логики.

Работа с null и отсутствующими значениями

Tooltip в Kepler.gl устойчив к отсутствующим данным, однако поведение зависит от конфигурации:

  • null обычно отображается как пустое значение
  • undefined пропускается
  • строки 'N/A' выводятся как есть

Рекомендуется нормализовать данные до передачи в слой:

const safeValue = (v) => v ?? '—';

Производительность при большом объёме данных

Tooltip формируется на лету, поэтому при больших наборах данных важно учитывать:

  • количество полей напрямую влияет на скорость сборки
  • сложные форматтеры замедляют hover-интеракции
  • вычисляемые значения лучше кэшировать заранее

Оптимизация:

const precomputedData = data.map(d => ({
  ...d,
  speed: d.distance / d.time
}));

Совместимость tooltip с фильтрацией данных

Kepler.gl фильтры (filters в visState) влияют на tooltip косвенно:

  • если объект отфильтрован, tooltip не отображается
  • если слой скрыт, tooltip отключается
  • фильтры временного диапазона влияют на доступность полей времени

Итоговая модель формирования tooltip

Финальная логика можно представить как цепочку:

Raw Data
  → Layer Selection
  → Interaction Detection
  → fieldsToShow Filtering
  → columnFormat Transformation
  → Optional Custom Tooltip Function
  → Render Output

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