Визуализация данных с помощью JavaScript и библиотеки D3

D3.js, или D3 – это библиотека JavaScript. Ее полное название – Data-Driven Documents. Это интерактивная и динамическая библиотека визуализации данных для сети.

Первая версия вышла в феврале 2011 года, а в июне 2016 года была выпущена D3 4. На момент написания последней стабильной версией была 4.4. Библиотека постоянно обновляется.

D3 использует масштабируемую векторную графику (или формат SVG), что позволяет отображать фигуры, линии и заливку, которые можно увеличивать или уменьшать без потери качества.

Этот мануал поможет вам создать гистограмму с помощью библиотеки JavaScript D3.

Требования

  • Базовые навыки работы с JavaScript, CSS и HTML.
  • Хотя в создании стилей D3 используется CSS, стоит отметить, что множество стандартных CSS, которые работают на HTML, работают на SVG иначе – то есть вы будете использовать stroke вместо border, fill вместо color. Чтобы узнать больше, вы можете прочитать статью Mozilla Developer Network о SVG и CSS.
  • Текстовый редактор и веб-браузер. Для тестирования рекомендуется использовать инструмент проверки и отладки JavaScript, HTML и CSS, например Firefox Developer Tools или Chrome DevTools.

1: Создание файлов и ссылок D3

Начнем с создания каталога для хранения файлов. Вы можете называть его, как хотите, а в мануале он будет называться D3-project. Создайте его и перейдите в этот каталог.

mkdir D3-project
cd D3-project

Чтобы использовать возможности D3, нужно включить файл d3.js в веб-страницу. Это около 16 000 строк и 500 КБ.

Используйте curl, чтобы загрузить файл в каталог.

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

curl https://d3js.org/d3.v4.min.js --output d3.min.js

Если вы планируете читать код D3, вероятно, лучше получить несжатую версию с удобочитаемыми пробелами:

curl https://d3js.org/d3.v4.js --output d3.js

В мануале мы используем d3.min.js, но если вы решите использовать удобочитаемую версию, тогда вместо этого укажите d3.js в своем HTML-файле.

Поскольку версия D3 4 является модульной, вы можете уменьшить размер файла, загрузив только те модули, которые будете использовать.

Загрузив D3, настройте файлы CSS и HTML. Вы можете выбрать любой текстовый редактор, например nano. Начнем с файла CSS, style.css, чтобы можно было сразу ссылаться на него из HTML-файла.

nano style.css

Начните со стандартного объявления CSS для стилизации страницы со 100% высотой и без полей.

html, body {
margin: 0;
height: 100%;
}

Сохраните и закройте файл CSS.

Затем создайте файл JavaScript, который будет называться barchart.js, потому что в этом примере мы собираемся создать гистограмму. В этом файле будет находиться большая часть кода D3, который вы напишете позже. Поскольку файл не нужно открывать прямо сейчас, можно использовать команду touch.

touch barchart.js

Пока что соедините все эти элементы с HTML-файлом, который будет называться barchart.html:

nano barchart.html

Вы можете настроить этот файл, как и большинство других HTML-файлов; в нем нужно сослаться на только что созданные файлы style.css и barchart.js, а также на сценарий d3.min.js.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bar Chart</title>
<link rel="stylesheet" type="text/css" href="style.css">
<!-- Alternatively use d3.js here -->
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<script type="text/javascript" src="barchart.js"></script>
</body>
</html>

Пока что сохраните и закройте его.

2: Настройка SVG в JavaScript

Откройте файл barchart.js:

nano barchart.js

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

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];

Затем нужно создать элемент SVG. Здесь нужно разместить все формы. Используйте в D3 d3.select, чтобы браузеру искал элементы.

Это можно сделать с помощью одной строки d3.select(«body»).append(«svg»);. Но было бы лучше объявить его как переменную, чтобы позже можно было легко ссылаться на нее в коде.

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg");

Если теперь вы загрузите barchart.html в браузере, вы сможете проверить объектную модель DOM с помощью инструментов для разработчиков и открыть окно SVG. В зависимости от вашего браузера оно может быть довольно маленьким.

Читайте также: Основы DOM

Вернитесь в файл JavaScript, чтобы привязать атрибуты к SVG и исправить высоту и ширину страницы. Используйте атрибут .attr(). Все это можно сохранить на одной строке, но для восприятия удобнее разбить их. Убедитесь, что вы переместили точку с запятой в конец объявления переменной.

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");

Теперь обновите страницу, и вы увидите, что прямоугольник отображается в полноэкранном режиме при наведении указателя мыши на DOM.

3: Добавление прямоугольников

Теперь SVG готов,можно двигаться дальше и добавить прямоугольники для отображения данных в файл JavaScript.

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect");

Как и в случае с d3.select, мы говорим браузеру искать элементы. На этот раз это массив прямоугольников. Поскольку это массив прямоугольников, нужно использовать d3.selectAll («rect»). Если браузер находит прямоугольники, он вернет их, если нет, результат будет пустым. В D3 нужно сначала выбрать элементы, с которыми вы собираетесь работать.

Привяжите этот массив прямоугольников к данным, хранящимся в dataArray, с помощью .data(dataArray).

Чтобы фактически добавить прямоугольник для каждого элемента в выборе (который соответствует массиву данных), нужно также добавить .enter().append(«rect»);. В этом примере будет 9 прямоугольников, соответствующих 9 числам в массиве.

Если вы сейчас перезагрузите страницу, вы пока не увидите никаких прямоугольников, но если вы проверите DOM, вы увидите там 9 прямоугольников.

Пока что вы не установили атрибуты для того, чтобы прямоугольники стали видимыми.

Настройка атрибутов фигур

Вы можете добавлять атрибуты к формам так же, как и атрибуты для SVG, используя .attr(). Каждая фигура в D3 имеет разные атрибуты в зависимости от того, как они определены и нарисованы.

Здесь прямоугольники будут иметь 4 атрибута:

  • («height», «height_in_pixels») для определения высоты прямоугольников
  • («width», «width_in_pixels») для определения ширины
  • («x», «distance_in_pixels») для определения расстояния от левой стороны окна браузера
  • («y», «distance_in_pixels») для определения расстояния от верхней части окна браузера

Итак, если, скажем, нам нужны прямоугольники 250 пикселей в высоту, 40 пикселей в ширину, с отступом 25 пикселей от левой стороны браузера и 50 пикселей сверху, код будет выглядеть следующим образом:

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("height","250")
.attr("width","40")
.attr("x","25")
.attr("y","50");

Обновите страницу, и вы увидите один прямоугольник – это потому, что все 9 прямоугольников сейчас одного цвета и накладываются друг на друга.

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

Отражение данных с помощью фигур

В настоящее время все прямоугольники в массиве занимают одинаковую позицию вдоль оси X и не отображают никаких данных по высоте.

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

Читайте также: Определение функций в JavaScript

Начнем с изменения атрибута x. В настоящее время эта строка кода выглядит так:

.attr("x","25")

Замените 25 пикселей функцией. Для этого передайте две переменные, определенные D3, в function(). Они будут отображать точку данных и индекс, где индекс указывает позицию точки данных внутри массива. По соглашению следует использовать d для точки данных и i для индекса, как в function(d, i), но вы можете использовать любые переменные, которые хотите.

JavaScript будет итерировать d и i. Теперь добавьте промежуток для каждого индекса, чтобы каждый прямоугольник отображался отдельно. Для этого можно умножить индекс i на определенное количество пикселей. Здесь мы будем использовать 60, но вы можете сами выбрать интервал. Теперь новая строка атрибута оси X выглядит так:

.attr("x", function(d, i) {return i * 60;})

Однако если вы запустите код сейчас, вы увидите, что прямоугольники сбрасываются в левую сторону браузера, поэтому добавьте дополнительные промежутки, скажем, 25 пикселей от края. Теперь полный код должен выглядеть так:

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("height","250")
.attr("width","40")
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y","50");

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

Теперь прямоугольники расположены вдоль оси X и отображают каждый из элементов массива. Давайте сделаем так, чтоб высота прямоугольников отражала данные в массиве.

Теперь нужно поработать с атрибутом height и добавить функцию, аналогичную атрибуту x. Передайте переменные d и i в function и верните d.

.attr("height", function(d, i) {return (d)})

Если вы сейчас запустите код, вы заметите две вещи. Во-первых, прямоугольники довольно маленькие, а во-вторых, они прикреплены к верхней части экрана, а не к нижней.

Чтобы увеличить размер прямоугольников, умножьте возвращаемую d:

.attr("height", function(d, i) {return (d * 10)})

Теперь прямоугольники стали больше, но они все еще отображаются сверху вниз.

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

Снова используйте функцию function(d, i) и верните Y, которое будет выше, чем наивысшее значение в гистограмме, например 400. Отнимите возвращаемую высоту (d * 10) из 400; строка теперь выглядит так:

.attr("y", function(d, i) {return 400 - (d * 10)});

Код JavaScript теперь имеет такой вид:

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("height", function(d, i) {return (d * 10)})
.attr("width","40")
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y", function(d, i) {return 400 - (d * 10)});

На этом этапе перезагрузите страницу и убедитесь, что гистограмма отображается правильно.

Теперь можно поработать над стилем диаграммы.

4: Стили в D3

Откройте CSS-файл, чтобы скомпоновать формы D3, но сначала, чтобы облегчить эту работу, нужно присвоить прямоугольникам имя класса в файле JavaScript, на которое вы сможете ссылаться в файле CSS.

Классы добавляется так же, как и другие атрибуты, с помощью точечной нотации. Назовем класс bar, так как это гистограмма (bar chart). Синтаксис будет выглядеть так:

.attr("class", "bar")

Добавьте этот атрибут в любое место файла barchart.js. Использование его в качестве первого атрибута упрощает обращение к нему в файле CSS.

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("class", "bar")
.attr("height", function(d, i) {return (d * 10)})
.attr("width","40")
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y", function(d, i) {return 400 - (d * 10)});

Вернитесь в файл style.css:

html, body {
margin: 0;
height: 100%
}

Здесь можно изменить цвет фигур, сославшись на класс bar:

html, body {
margin: 0;
height: 100%
}
.bar {
fill: blue
}

Теперь все фигуры в графике будут синими. Также вы можете назначить им шестнадцатеричный цветовой код:

.bar {
fill: #0080FF
}

Обновите страницу.

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

html, body {
margin: 0;
height: 100%
}
.bar {
fill: #0080FF;
stroke: black;
stroke-width: 5
}

Прямоугольники будут обведены черным контуром шириной 5 пикселей.

Кроме того, к диаграмме можно добавить интерактивность: цвет фигуры изменится при наведении мыши.

.bar:hover {
fill: red
}

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

Кроме того, вы можете создавать фигуры в файле JavaScript, добавляя новые атрибуты. В блоке прямоугольника они записываются так же, как и другие атрибуты .attr(). То есть, добавление обводки вокруг прямоугольников будет записано как .attr(«stroke», «black»). Добавьте ширину штриха в 5 пикселей и обязательно переместите точку с запятой.

...
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("class", "bar")
.attr("height", function(d, i) {return (d * 10)})
.attr("width","40")
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y", function(d, i) {return 400 - (d * 10)})
.attr("stroke", "black")
.attr("stroke-width", "5");

Стиль ваших фигур и файл, в котором вы его определяете, полностью зависит от вашего выбора. В этом примере мы работаем в файле style.css.

html, body {
margin: 0;
height: 100%
}
.bar {
fill: #0080FF
}
.bar:hover {
fill: #003366
}

При работе с цветами в Интернете важно помнить об аудитории и включать цвета, которые являются как можно более доступными. Чтобы узнать больше о доступности цветов, вы можете обратиться к Acessibility & Me.

5: Добавление меток

Последний шаг – добавить количественные метки в график. Эти метки будут отображать числа в массиве.

Текст добавляется аналогично фигурам прямоугольника. Вам нужно выбрать текст, а затем добавить его в SVG. Также его нужно привязать к созданному DataArray. Вместо «rect» нужно использовать «text», но общий формат аналогичен добавлению фигур. Поместите эти строки в конец файла barchart.js.

var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("class", "bar")
.attr("height", function(d, i) {return (d * 10)})
.attr("width","40")
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y", function(d, i) {return 400 - (d * 10)});
svg.selectAll("text")
.data(dataArray)
.enter().append("text")
.text(function(d) {return d;});

Когда вы обновите браузер, вы не увидите ни одного текста на странице, но он есть в DOM.

Если вы наведите указатель мыши на строки текста в DOM, вы увидите, что текст находится в верхней части страницы, где X и Y равны 0. Измените его позицию, используя те же формулы функций, что и для прямоугольников.

...
svg.selectAll("text")
.data(dataArray)
.enter().append("text")
.text(function(d) {return d})
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y", function(d, i) {return 400 - (d * 10)});

Обновите страницу и вы увидите числа над прямоугольниками.

Стоит отметить, что, поскольку это SVG, а не изображение, вы можете выбирать текст так же, как и любой другой текст, который вы видите на странице.

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

...
svg.selectAll("text")
.data(dataArray)
.enter().append("text")
.text(function(d) {return d})
.attr("x", function(d, i) {return (i * 60) + 36})
.attr("y", function(d, i) {return 390 - (d * 10)});

Кроме того, вы можете поместить числа в прямоугольники путем изменения их положения в оси Y. Также можно сделать код более удобочитаемым, поэтому давайте добавим класс, на который можно ссылаться из файла style.css.

...
svg.selectAll("text")
.data(dataArray)
.enter().append("text")
.text(function(d) {return d})
.attr("class", "text")
.attr("x", function(d, i) {return (i * 60) + 36})
.attr("y", function(d, i) {return 415 - (d * 10)});

Перейдите в style.css и сделайте текст белым и без засечек, добавив следующие строки в конец файла.

...
.text {
fill: white;
font-family: sans-serif
}

Вы можете изменить текст, сколько хотите, с помощью позиционирования и стилизации. Например, вы также можете изменить атрибут font-size в файле style.css.

Совершенствование и улучшение кода

На этом этапе у вас должна быть полностью функционирующая гистограмма, отображаемая в библиотеке D3 JavaScript. Так выглядит barchart.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bar Chart</title>
<!-- Reference style.css -->
<link rel = "stylesheet" type="text/css" href="style.css">
<!-- Reference minified version of D3 -->
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<script type="text/javascript" src="barchart.js"></script>
</body>
</html>

Это style.css:

html, body {
margin: 0;
height: 100%
}
/*Rectangle bar class styling*/
.bar {
fill: #0080FF
}
.bar:hover {
fill: #003366
}
/*Text class styling*/
.text {
fill: white;
font-family: sans-serif
}

А это – barchart.js:

// Create data array of values to visualize
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
// Create variable for the SVG
var svg = d3.select("body").append("svg")
.attr("height","100%")
.attr("width","100%");
// Select, append to SVG, and add attributes to rectangles for bar chart
svg.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.attr("class", "bar")
.attr("height", function(d, i) {return (d * 10)})
.attr("width","40")
.attr("x", function(d, i) {return (i * 60) + 25})
.attr("y", function(d, i) {return 400 - (d * 10)});
// Select, append to SVG, and add attributes to text
svg.selectAll("text")
.data(dataArray)
.enter().append("text")
.text(function(d) {return d})
.attr("class", "text")
.attr("x", function(d, i) {return (i * 60) + 36})
.attr("y", function(d, i) {return 415 - (d * 10)});

Этот код полностью работает, но вы можете улучшить и расширить его. Например, вы можете использовать элемент group SVG для группировки элементов SVG, что позволяет вам изменять текст и прямоугольники с меньшим количеством строк кода.

Вы также можете по-разному получать доступ к данным. Для хранения данных мы использовали массив, но вы можете визуализировать данные, к которым у вас уже есть доступ, и у вас может быть значительно больше данных. D3 позволяет работать с различными типами файлов данных:

  • HTML
  • JSON
  • Простой текст
  • CSV (значения, разделенные запятыми)
  • TSV (значения, разделённые знаками табуляции)
  • XML

Например, вы можете поместить JSON-файл в каталог своего веб-сайта и подключать его к файлу JavaScript:

d3.json("myData.json", function(json) {
// code for D3 charts in here
});

Вы также можете объединить библиотеку D3 с другими интерактивными функциями JavaScript.

Заключение

В этом мануале вы создали гистограмму в библиотеке JavaScript D3. Вы можете узнать больше о d3.js, посетив D3 API на GitHub.

Читайте также: Визуализация данных Python 3 с помощью matplotlib

Tags: , , , ,