Последовательные шкалы в D3.js предназначены для преобразования числового непрерывного диапазона значений в непрерывный диапазон цветов или других визуальных параметров через интерполяцию. В отличие от линейных шкал, которые возвращают дискретно вычисляемые значения диапазона, последовательные шкалы используют функцию интерполяции, обеспечивая плавный переход между значениями без разрывов.
Основой последовательной шкалы является отображение вида:
x ∈ [a, b] → t ∈ [0, 1] → color = f(t)
где промежуточное значение t нормализуется, а затем передаётся в интерполятор, формирующий итоговое значение.
d3.scaleSequential()Функция d3.scaleSequential() создаёт шкалу, которая
принимает интерполятор и возвращает функцию масштабирования.
const scale = d3.scaleSequential(d3.interpolateViridis)
.domain([0, 100]);
В этом примере:
.domain([0, 100])d3.interpolateViridis определяет цветовую
шкалуПри вызове:
scale(0); // начало диапазона
scale(50); // середина
scale(100); // конец диапазона
возвращаются значения, находящиеся на непрерывной цветовой градиентной шкале.
Последовательная шкала не использует классический range.
Вместо этого она полагается на интерполятор, который принимает
нормализованное значение t:
t = (x - domainMin) / (domainMax - domainMin)
Затем:
output = interpolator(t)
Интерполятор может работать с цветами, числами, массивами и другими структурами данных, если они поддерживают линейную интерполяцию.
d3.scaleLinear()Линейная шкала возвращает значения из фиксированного массива диапазона:
d3.scaleLinear()
.domain([0, 100])
.range(["blue", "red"]);
Последовательная шкала же работает иначе:
d3.scaleSequential(d3.interpolateBlues)
.domain([0, 100]);
Ключевые различия:
rangeinterpolatorОсновная сила d3.scaleSequential() заключается в
использовании встроенных интерполяторов.
Наиболее часто используются:
d3.interpolateViridisd3.interpolateInfernod3.interpolateMagmad3.interpolatePlasmad3.interpolateCividisd3.interpolateBluesd3.interpolateGreensd3.interpolateRedsПример:
const colorScale = d3.scaleSequential(d3.interpolatePlasma)
.domain([0, 1]);
Эти интерполяторы обеспечивают визуально равномерные градиенты, что особенно важно в научной визуализации.
Интерполяция возможна не только для цветов:
d3.interpolateNumber(0, 100)(0.5); // 50
Также поддерживаются:
d3.interpolateRgbd3.interpolateHsld3.interpolateLabd3.interpolateObjectПоследний вариант позволяет интерполировать сложные структуры:
d3.interpolateObject(
{x: 0, y: 0},
{x: 10, y: 20}
)(0.5); // {x: 5, y: 10}
Домены в последовательных шкалах всегда числовые и обычно двухточечные:
const scale = d3.scaleSequential(d3.interpolateViridis)
.domain([minValue, maxValue]);
Если значения выходят за пределы диапазона, они автоматически интерполируются за его границами, если не включено ограничение:
scale.clamp(true);
В этом случае значения фиксируются на границах домена.
Математически процесс можно представить как композицию функций:
scale(x) = interpolator( normalize(x) )
где:
normalize(x) = (x - min) / (max - min)
Это делает последовательные шкалы особенно удобными для визуализаций, где требуется плавное изменение цвета или интенсивности.
Последовательные шкалы часто применяются в:
Пример применения к SVG-элементам:
const color = d3.scaleSequential(d3.interpolateViridis)
.domain([0, 100]);
d3.selectAll("circle")
.attr("fill", d => color(d.value));
Последовательные шкалы не предназначены для обратного преобразования (invert) в стандартном виде. В отличие от линейных шкал, где возможно:
scale.invert(value)
для последовательных шкал такая операция обычно отсутствует или требует дополнительной логики, поскольку интерполятор не всегда обратим.
Одно из ключевых преимуществ последовательных шкал — перцептивная равномерность. Некоторые интерполяторы, такие как Viridis, разработаны так, чтобы:
В D3 существуют специализированные версии последовательных шкал:
d3.scaleSequentialLog()Используется для логарифмически распределённых данных:
d3.scaleSequentialLog(d3.interpolatePlasma)
d3.scaleSequentialPow()Позволяет задавать степенную трансформацию:
d3.scaleSequentialPow(d3.interpolateViridis)
.exponent(2);
d3.scaleSequentialSqrt()Частный случай степенной функции с экспонентой 0.5:
d3.scaleSequentialSqrt(d3.interpolateInferno)
Эти варианты полезны при работе с неравномерно распределёнными данными, где линейное отображение искажает восприятие.
Последовательная шкала может использовать пользовательскую функцию:
const customInterpolator = t => `rgba(${255 * t}, 0, ${255 * (1 - t)}, 1)`;
const scale = d3.scaleSequential(customInterpolator)
.domain([0, 100]);
Такой подход позволяет создавать нестандартные визуальные эффекты и гибко управлять градиентами.
При работе с реальными данными часто требуется предварительная обработка:
Пример:
const extent = d3.extent(data, d => d.value);
const color = d3.scaleSequential(d3.interpolateViridis)
.domain(extent);
Если значение выходит за пределы домена, поведение зависит от настройки:
clamp: интерполятор может экстраполировать
значенияclamp(true): значение фиксируется на ближайшей
границеscale.clamp(true);
Это особенно важно в визуализациях, где экстремальные значения могут искажать цветовую картину.
Последовательные шкалы часто выступают базовым компонентом более сложных систем визуализации:
В таких случаях шкала выступает как детерминированная функция отображения, обеспечивающая согласованность визуального представления при любых трансформациях данных.