Цветовая шкала в визуализации определяет, как числовые или категориальные значения преобразуются в цвета. В контексте D3.js работа с цветом опирается на систему масштабов (scales) и интерполяций, где выбор неправильного подхода может полностью исказить восприятие данных.
Непрерывные шкалы используются для отображения упорядоченных числовых данных, где важно сохранить ощущение градиента.
Основная идея — монотонное изменение цвета от минимального к максимальному значению.
В D3 такие шкалы обычно строятся через:
d3.scaleSequential(d3.interpolateViridis);
или через числовую доменную функцию:
d3.scaleSequential()
.domain([0, 100])
.interpolator(d3.interpolatePlasma);
Цвета должны изменяться равномерно с точки зрения восприятия, а не только математически.
Используются, когда данные имеют центральную точку отсчёта (например, 0), и отклонения в обе стороны одинаково важны.
d3.scaleDiverging(d3.interpolateRdBu)
.domain([-10, 0, 10]);
Центр должен быть осмысленно выбран. Неверная установка домена делает визуализацию статистически некорректной.
Используются для дискретных категорий.
d3.scaleOrdinal(d3.schemeCategory10);
или
d3.scaleOrdinal()
.domain(["A", "B", "C"])
.range(["#1f77b4", "#ff7f0e", "#2ca02c"]);
Порядок категорий не имеет числового смысла, поэтому важна различимость цветов, а не градиент.
D3.js предоставляет набор perceptual interpolators:
d3.interpolateViridisd3.interpolateInfernod3.interpolateMagmad3.interpolatePlasmad3.interpolateCividisЭти палитры основаны на восприятии яркости и равномерности переходов.
d3.scaleSequential()
.domain([0, 1])
.interpolator(d3.interpolateViridis);
Цветовые схемы типа «радужной шкалы» (rainbow) визуально привлекательны, но приводят к искажениям:
Например:
d3.scaleSequential(d3.interpolateRainbow);
Такая шкала редко подходит для аналитических задач.
Человеческое зрение не воспринимает RGB-пространство линейно. Поэтому линейная интерполяция в RGB приводит к:
Лучшие альтернативы:
В D3 интерполяции уже учитывают эти особенности через специализированные функции.
Разбивает непрерывный диапазон на фиксированные интервалы:
d3.scaleQuantize()
.domain([0, 100])
.range(["#f7fbff", "#08306b"]);
Используется для:
Разделяет данные по квантилям:
d3.scaleQuantile()
.domain(dataArray)
.range(colorScheme);
Особенность:
Ручное определение границ:
d3.scaleThreshold()
.domain([10, 20, 50])
.range(["green", "yellow", "orange", "red"]);
Используется в:
Категориальные шкалы должны учитывать:
Проблема возникает при превышении ~10–12 категорий: цвета начинают повторяться или сливаться.
Типичный пример:
d3.scaleOrdinal(d3.schemeTableau10);
Наиболее распространённые формы:
Нежелательные комбинации:
При наложении цветов на фон необходимо учитывать коэффициент контраста.
Слабый контраст приводит к:
Ошибкой является прямое применение цветовой шкалы к «сырым» данным без предварительного анализа распределения.
Типичные проблемы:
Решение:
Пример логарифмической трансформации:
d3.scaleSequential()
.domain([1, 1000])
.interpolator(d3.interpolateViridis)
.clamp(true);
Прозрачность часто используется как дополнительное измерение.
Ошибки:
Рекомендуется:
На тёмном фоне восприятие цвета меняется:
Типичный подход:
| Интерполятор | Особенность |
|---|---|
| Viridis | равномерная яркость |
| Inferno | высокая контрастность |
| Plasma | яркие насыщенные цвета |
| Magma | тёплая гамма |
| Cividis | оптимизирован для дальтонизма |
Цвет начинает восприниматься как отдельная переменная, а не отображение данных.
Слишком большое количество цветов разрушает структуру визуализации.
Равномерная шкала при сильно скошенных данных создаёт ложную интерпретацию.
Rainbow и случайные наборы цветов создают визуальный шум вместо информации.
При создании пользовательских шкал важно контролировать не только оттенок, но и luminance:
d3.scaleSequential()
.domain([0, 1])
.interpolator(t => d3.interpolateLab("white", "steelblue")(t));
Lab-интерполяция обеспечивает более корректное восприятие переходов.
Цветовая шкала должна соответствовать семантике:
Нарушение семантики приводит к когнитивному диссонансу при интерпретации визуализации.
При изменении масштаба графика важно сохранять:
В D3 это достигается фиксацией домена и пересчётом шкалы только при изменении данных, а не отображения.