Распространенное заблуждение о D3 среди тех, кто еще не использовал его, заключается в том, что он предоставляет набор инструментов графиков и диаграмм, которые можно использовать для визуализации своих данных. То есть вы подключаете вход, выбираете «круговую диаграмму» и вуаля!, у вас есть визуализация. На самом деле, это более точно описывает множество библиотек построения диаграмм, построенных поверх D3, в то время как инструменты, которые предоставляет D3, находятся на более глубоком уровне.
D3 — это библиотека не столько для создания диаграмм и графиков, сколько для сопоставления набора точек данных с набором элементов DOM. Это помогает нам определить отношение между данными и их визуальным представлением. Основным строительным блоком этого отношения в D3 является шкала.
Что такое шкала?
Шкалы в D3 — это на самом базовом уровне функции, которые принимают входное значение и возвращают выходное значение. Самый простой тип шкалы — это линейная шкала, которую мы можем определить следующим образом:
const scale = d3.scaleLinear()
Это дает нам функцию scale
, которую мы можем передать в значениях:
scale(75) // returns 75
Но подождите… это только что вернуло нам наш вклад. Это связано с тем, что шкала дает нам тип отношения (в данном случае линейного), но для того, чтобы на самом деле его использовать, нам нужно определить границы этого отношения. Связь между входом и выходом определяется пользователем как домен и диапазон.
Домены и диапазоны
Домен представляет входные данные — это диапазон возможных входных значений из нашего набора данных. Например, если у нас есть входной массив, который выглядит как
[5,24,31,85,97, 101, 138, 145]
мы могли бы настроить наш домен так, чтобы он простирался от самых низких до самых высоких значений в этом наборе, выраженном здесь как [5, 145]
. Если бы мы выбирали ось диаграммы, возможно, имело бы смысл округлить эти значения до [0, 150]
.
Диапазон, с другой стороны, является выходом — это диапазон возможных выходных значений, которые возвращает нам наша шкала. Обычно это измерения в пикселях элементов DOM, из которых состоит наша визуализация. Например, высота столбцов на гистограмме или цвет области на карте.
Чтобы определить наш домен и диапазон, мы можем просто расставить точки над функцией масштабирования, которую мы определили ранее.
scale.domain([0, 150]) .range([100, 500])
Теперь, если мы попытаемся снова вызвать scale(75)
, вместо того, чтобы вернуть наше входное значение, мы получим 300
. Точно так же, как 75 — это середина нашего домена (0-150), 300 — это середина нашего диапазона (100-500). Довольно круто, правда?
Непрерывные весы
В D3 существует множество различных масштабов, и линейные масштабы являются примером особого типа, известного как непрерывные масштабы. Как мы рассмотрели выше, непрерывная шкала может брать любую точку из входной области и возвращать соответствующую точку в выходном диапазоне.
Другими типами непрерывных шкал в D3 являются шкала мощности, логарифмическая шкала, шкала идентичности и шкала времени. Все они аналогичны линейным шкалам, но основное отличие заключается в преобразовании, которое применяется к входному значению до того, как будет вычислено выходное значение. В то время как линейные шкалы используют линейную функцию (y = m * x + b
), шкалы мощности используют экспоненциальную функцию (y = m * x^k + b
), логарифмические шкалы используют логарифмическую функцию и т. д.
Чтобы глубже понять, как именно работают непрерывные шкалы, давайте взглянем на код, из которого состоит D3. Если мы покопаемся, чтобы увидеть, где именно определена наша функция scaleLinear()
, мы обнаружим следующее:
Если мы посмотрим на scalePow()
, мы увидим нечто подобное:
Так что же именно здесь происходит? Функция linearish
просто дает нам ticks
, nice
и некоторые другие классные функции, которые помогают нам форматировать наши весы. Основная часть работы происходит в continuous
, который называется в определении каждой из непрерывных шкал D3.
continuous
принимает два параметра, deinterpolate
и reinterpolate
, и это функции, определяющие поведение наших весов. Тело этих функций будет различаться в зависимости от того, какую непрерывную шкалу мы рассматриваем (линейную, степенную и т. д.), но в целом они ведут себя одинаково.
Комментарии Майка Бостока к коду D3 дают нам краткое объяснение того, как работают эти функции.
// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
Другими словами, каждая функция принимает входные значения, которые мы указываем для нашего домена, и возвращает другую функцию, которая сама принимает значение. Для deinterpolate
значение, которое он принимает, x
, является любым значением в пределах [a, b]
нашего домена. Он берет это значение x
и преобразует его, возвращая значение t
в диапазоне от 0 до 1. Функция reinterpolate
— это просто обратная функция, которая дает нам функцию, которая принимает t
в диапазоне от 0 до 1 и возвращает соответствующее значение x
в пределах нашего домена.
Здесь происходит процесс, известный как нормализация, который представляет собой сопоставление значения с другим значением от 0 до 1 на основе возможных минимального и максимального значений. В приведенном выше примере линейной шкалы, где вызов scale(75)
возвращает нам 300
, функция, возвращаемая deinterpolate
, принимает 75 и возвращает 0,5, или 50%, которые затем применяются к выходному диапазону, чтобы дать нам наш результат.
В конечном счете, это простая концепция, которая в конечном итоге становится сверхмощной. Непрерывные масштабы D3 абстрагируются от математики, лежащей в основе нормализации, и дают нам быстрый, многоразовый способ сопоставления значения в наборе входных данных с соответствующим значением в наборе выходных данных.
В заключении …
В D3 есть все виды различных гамм. Шкалы квантования, например, делят выходной диапазон на дискретные сегменты. Порядковые шкалы вообще не нуждаются в числовом домене и могут сопоставлять набор именованных категорий с набором цветов или с позициями на диаграмме. Ознакомьтесь с приведенными ниже ресурсами, чтобы узнать больше о масштабах и D3 в целом. Как только вы поймете, что может сделать эта мощная библиотека, возможности безграничны. Удачного кодирования!