Используйте возможности D3.js для создания красивых представлений ваших данных.

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

В этом уроке мы собираемся создать линейную диаграмму, отображающую индекс цен на биткойны за последние шесть месяцев. Мы будем извлекать данные из внешнего API и визуализировать линейную диаграмму с метками и осью внутри DOM.

Мы также создали бесплатный курс D3.js по Scrimba. Посмотрите здесь.

Начиная

Прежде всего, мы импортируем библиотеку D3.js прямо из CDN внутри нашего HTML.

<html>
  <head>
    <link rel="stylesheet" href="index.css">
  </head>
  <body>
    <svg></svg>
    <script src="https://d3js.org/d3.v4.min.js"></script>  </body>
</html>

Мы также добавили тег <svg></svg> в наш HTML-код, чтобы создать внутри него линейную диаграмму с помощью D3.js.

Теперь перейдем к написанию нашего кода JavaScript. Прежде всего, мы хотим загрузить наши данные индекса цен на биткойны из внешнего API после загрузки DOM.

Получить данные

var api = 'https://api.coindesk.com/v1/bpi/historical/close.json?start=2017-12-31&end=2018-04-01';
document.addEventListener("DOMContentLoaded", function(event) {
   fetch(api)
     .then(function(response) { return response.json(); })
     .then(function(data) { 
         //DO SOMETHING WITH DATA  
     })
});

В приведенном выше коде мы используем метод fetch для получения данных из внешнего API. Затем мы анализируем его с помощью метода .json().

Теперь мы хотим преобразовать эти данные в пары ключ / значение, чтобы они были в формате date:price. Для этого мы собираемся отправить наши данные в другую функцию, которая проанализирует и вернет их в желаемой форме.

Анализировать данные

....
.then(function(data) { 
         var parsedData = parseData(data)
 })
function parseData(data) {
   var arr = [];
   for (var i in data.bpi) {
      arr.push(
         {
            date: new Date(i), //date
            value: +data.bpi[i] //convert string to number
         });
   }
   return arr;
}

Мы передаем наши данные функции parseData, которая возвращает другой массив объектов. Каждый объект содержит дату и цену биткойна на эту конкретную дату.

Как только у нас будут данные в требуемом формате, мы отправим эти данные в функцию drawChart, в которой весь оставшийся код будет записан с использованием D3.js для визуализации линейной диаграммы.

....
.then(function(data) { 
   var parsedData = parseData(data);
   drawChart(parsedData);
})

Выберите элемент SVG

В функции drawChart мы в первую очередь выбираем наш элемент SVG и придаем ему некоторый стиль.

function drawChart(data) {
   var svgWidth = 600, svgHeight = 400;
   var margin = { top: 20, right: 20, bottom: 30, left: 50 };
   var width = svgWidth - margin.left - margin.right;
   var height = svgHeight - margin.top - margin.bottom;
   var svg = d3.select('svg')
     .attr("width", svgWidth)
     .attr("height", svgHeight);
...

В приведенном выше коде мы устанавливаем ширину и высоту контейнера SVG, сначала выбирая его с помощью метода select(), а затем используя метод attr() для назначения атрибутов.

Мы также определили поля и используем их значения при вычислении атрибутов ширины и высоты контейнера SVG. Эти значения маржи помогут нам в дальнейшем правильно позиционировать и отображать нашу диаграмму.

Используя CSS, мы задали границы нашему контейнеру SVG:

<style>
    .line-chart
    {
        border: 1px solid lightgray;
    }
</style>

Пока что внутри нашего DOM ничего нет:

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

Создание и преобразование элемента группы

...
var g = svg.append("g")
   .attr("transform", 
      "translate(" + margin.left + "," + margin.top + ")"
   );

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

D3 дает нам различные варианты трансформации наших элементов. В приведенном выше коде мы используем свойство translate для изменения положения нашего элемента группы с полями слева и сверху.

Добавить весы

Теперь мы хотим добавить шкалу к нашей диаграмме.

var x = d3.scaleTime().rangeRound([0, width]);
var y = d3.scaleLinear().rangeRound([height, 0]);

Как мы знаем, наши данные состоят из дат и стоимости биткойнов на эти даты. Следовательно, мы можем предположить, что ось x будет содержать даты, а ось y будет содержать значения. Вот как мы можем увидеть изменение графика во времени.

Итак, в приведенном выше фрагменте кода мы создали шкалу типа времени по оси x и линейного типа по оси y. Мы также предоставляем эти шкалы с диапазонами в соответствии с шириной и высотой нашего контейнера SVG.

Создать линию

Теперь перейдем к определению нашей линии с помощью метода d3.line. Мы будем определять атрибуты x и y строки, передавая анонимные функции и возвращая объект даты и значение биткойна для этого конкретного дня.

var line = d3.line()
   .x(function(d) { return x(d.date)})
   .y(function(d) { return y(d.value)})
   x.domain(d3.extent(data, function(d) { return d.date }));
   y.domain(d3.extent(data, function(d) { return d.value }));

Добавить оси

Теперь мы собираемся добавить наши левую и нижнюю оси внутри элемента группы для линейного графика. Левая ось будет представлять стоимость биткойнов, а нижняя ось отображает соответствующую дату.

g.append("g")
   .attr("transform", "translate(0," + height + ")")
   .call(d3.axisBottom(x))
   .select(".domain")
   .remove();

В приведенном выше коде мы добавляем элемент группы внутри нашей основной группы и переводим его в самый низ нашего контейнера. Затем мы передаем метод d3.axisBottom в функцию вызова, где d3.axisBottom принимает параметр x, который определен в разделе Добавить масштаб.

g.append("g")
   .call(d3.axisLeft(y))
   .append("text")
   .attr("fill", "#000")
   .attr("transform", "rotate(-90)")
   .attr("y", 6)
   .attr("dy", "0.71em")
   .attr("text-anchor", "end")
   .text("Price ($)");

Подобно нижней оси, мы добавляем еще один элемент группы, а затем вызываем для него метод d3.axisLeft, который принимает параметр y. Затем мы также стилизуем нашу ось, назначая ей разные атрибуты и метку.

Если мы сохраним и обновим страницу, мы увидим, что наши оси отображаются внутри DOM:

Добавить путь

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

Мы передаем наш набор данных с помощью метода datum, а затем устанавливаем атрибуты цвета заливки, цвета обводки и ширины. В конце мы устанавливаем атрибут d, который фактически дает инструкции пути SVG о том, где соединить точки пути.

g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);

Вот окончательный результат:

Заключение

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

Если вы хотите узнать больше о D3.js, обязательно посетите наш бесплатный курс по Scrimba.

Я Сохаиб Нехал. Я разработчик веб-приложений полного стека. Вы можете связаться со мной по адресу [email protected] или в Twitter @Sohaib_Nehal. Спасибо :-)