Цветовые шкалы и пустые дни

Цветовые шкалы в Nivo формируют основу визуальной интерпретации данных: от простых категориальных наборов до сложных непрерывных градиентов, отражающих числовые диапазоны. Практически каждый график в библиотеке опирается на механизм преобразования значения в цвет, и от выбора шкалы напрямую зависит читаемость визуализации.

Основные типы цветовых шкал

В Nivo используются три ключевых подхода к окрашиванию данных:

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

Пример базового массива цветов:

const colors = ['#e8c1a0', '#f47560', '#f1e15b', '#e8a838', '#61cdbb'];

В компонентах Nivo этот массив часто передается напрямую:

<ResponsiveBar
  data={data}
  keys={['value']}
  indexBy="label"
  colors={{ scheme: 'set2' }}
/>

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


2. Последовательные (sequential) шкалы Предназначены для отображения числовых значений, изменяющихся в одном направлении. Чем выше значение, тем интенсивнее цвет.

Пример применения:

colors={{ scheme: 'blues' }}

Такие шкалы особенно эффективны в тепловых картах и календарных представлениях, где требуется визуально выделить плотность или интенсивность.


3. Дивергентные шкалы Используются, когда важно отразить отклонение от центрального значения (например, ноль). Цвета расходятся в противоположные стороны от нейтральной точки.

colors={{ scheme: 'red_yellow_blue' }}

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


Цветовые схемы d3 и интеграция с Nivo

Nivo опирается на экосистему D3, включая пакет d3-scale-chromatic. Это дает доступ к широкому набору предустановленных палитр:

  • nivo
  • category10
  • accent
  • dark2
  • paired
  • set1, set2, set3
  • blues, greens, oranges, reds

Пример использования схемы:

<ResponsiveLine
  data={data}
  colors={{ scheme: 'category10' }}
/>

Каждая схема оптимизирована под определённые сценарии: контраст, различимость, цветовая слепота, плотность данных.


Индивидуальная настройка цветовых функций

Помимо предустановленных схем, Nivo поддерживает функции, вычисляющие цвет динамически.

Пример:

colors={(bar) => {
  if (bar.value > 100) return '#ff4d4f';
  if (bar.value > 50) return '#faad14';
  return '#52c41a';
}}

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


Интерполяция и непрерывные шкалы

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

colors={{
  type: 'sequential',
  scheme: 'blues'
}}

В более сложных случаях используется d3-interpolate:

import { interpolateRgb } from 'd3-interpolate';

const colorScale = (value) =>
  interpolateRgb('#e0f3f8', '#08589e')(value);

Такая модель позволяет создавать плавные градиенты, особенно важные для heatmap и density-графиков.


Управление доменом значений

Цветовая шкала всегда связана с диапазоном значений. В Nivo этот диапазон может задаваться явно или вычисляться автоматически.

<ResponsiveHeatMap
  data={data}
  minValue={0}
  maxValue={100}
  colors={{ scheme: 'greens' }}
/>

Явное задание границ стабилизирует визуализацию при изменении входных данных.


Пустые дни и отсутствие данных

При работе с временными рядами и календарными представлениями возникает отдельная проблема — отсутствие данных в отдельных точках времени. В Nivo это особенно заметно в компонентах:

  • Calendar
  • TimeRange
  • HeatMap
  • Line

Понятие «пустого дня»

Пустой день — это дата, для которой отсутствует значение в исходном наборе данных. Визуально это может означать:

  • отсутствие ячейки,
  • серый цвет,
  • нулевое значение,
  • или специальное состояние «no data».

В зависимости от конфигурации Nivo выбирает один из этих вариантов.


Обработка отсутствующих значений

В линейных графиках поведение определяется полем null или undefined:

data: [
  {
    id: 'series-1',
    data: [
      { x: '2024-01-01', y: 10 },
      { x: '2024-01-02', y: null },
      { x: '2024-01-03', y: 15 }
    ]
  }
]

Поведение системы зависит от настроек:

  • null может разрывать линию
  • может интерполироваться
  • может игнорироваться

Для управления используется свойство:

<ResponsiveLine
  enablePoints={true}
  useMesh={true}
  connectNulls={false}
/>

Пустые дни в календарных визуализациях

В Calendar компоненте отсутствие данных приводит к отображению нейтральных ячеек.

<ResponsiveCalendar
  data={data}
  from="2024-01-01"
  to="2024-12-31"
  emptyColor="#eeeeee"
  colors={['#d6e685', '#8cc665', '#44a340', '#1e6823']}
/>

Ключевым параметром является:

  • emptyColor — цвет ячеек без данных

Если значение для даты отсутствует, ячейка автоматически окрашивается в этот цвет.


Логика сопоставления дат

Nivo строит внутреннюю карту дат на основе диапазона fromto. Для каждой даты происходит проверка:

  1. существует ли запись в данных
  2. есть ли числовое значение
  3. соответствует ли оно заданному домену

Если хотя бы один пункт не выполнен, дата считается пустой.


Пустые значения в HeatMap

В HeatMap отсутствие данных не всегда приводит к визуальной пустоте. Возможны три сценария:

1. Ячейка отсутствует полностью Данные не содержат записи.

2. Ячейка отображается с нейтральным цветом

emptyColor="#f0f0f0"

3. Ячейка отображается с минимальным значением шкалы

minValue={0}

Управление отображением пустых значений

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

const normalized = dates.map(d => ({
  x: d.date,
  y: d.value ?? 0
}));

Такой подход устраняет «разрывы» в визуализации, но искажает статистику, если ноль не является корректной заменой отсутствия данных.

Альтернативный вариант — сохранение null и визуальное разграничение:

const normalized = dates.map(d => ({
  x: d.date,
  y: d.value ?? null
}));

Визуальные стратегии для пустых дней

В интерфейсах на основе Nivo применяются несколько устойчивых паттернов:

Нейтральный фон Использование серого оттенка для отсутствующих значений.

Снижение насыщенности Пустые ячейки окрашиваются в ту же шкалу, но с минимальной интенсивностью.

Полное скрытие Ячейки не рендерятся, создавая визуальные «разрывы».

Подсказки при наведении Tooltip сообщает об отсутствии данных вместо числового значения.


Влияние пустых значений на цветовые шкалы

Цветовые шкалы и пустые дни связаны напрямую: шкала определяет, как интерпретировать диапазон, а отсутствие данных определяет разрыв этого диапазона.

При использовании sequential-шкал пустые значения часто попадают ниже минимального уровня и отображаются как emptyColor. В diverging-шкалах отсутствие данных не интерпретируется как отклонение и требует отдельного визуального состояния.


Стабильность визуализации при неполных данных

При динамических источниках данных (API, стриминг, аналитика) пустые дни становятся частым явлением. Для сохранения стабильной визуальной структуры применяются:

  • фиксация диапазона дат
  • предзаполнение массива значений
  • явное управление minValue и maxValue
  • унификация формата данных перед рендером
const filled = range.map(date => ({
  day: date,
  value: rawMap[date] ?? null
}));

Такой подход предотвращает «прыгающую» шкалу и сохраняет предсказуемость цветов.


Сочетание цветовых шкал и пустых состояний

Наиболее сложные визуализации возникают при комбинировании:

  • непрерывных шкал
  • календарных сеток
  • пропусков в данных

В таких случаях цветовая система разделяется на два слоя:

  1. шкала значений (data-driven)
  2. слой отсутствия данных (state-driven)

Это позволяет отделить «ноль как значение» от «пустоты как отсутствия информации», что критично для аналитических интерфейсов.