В предыдущей статье мы узнали, как реализовать пузырьковые диаграммы, используя D3.js , библиотеку JavaScript для создания документов, управляемых данными. D3.js помогает визуализировать данные с использованием HTML, SVG и CSS. В этой статье мы увидим, как реализовать линейные и гистограммы, используя D3.js. Прежде чем двигаться дальше, вам следует скачать D3.js и ознакомиться с материалами моей предыдущей статьи .
Создание линейных графиков
Сначала нам понадобятся некоторые данные для построения графика. Мы собираемся использовать следующие данные.
var lineData = [{ x: 1, y: 5 }, { x: 20, y: 20 }, { x: 40, y: 10 }, { x: 60, y: 40 }, { x: 80, y: 5 }, { x: 100, y: 60 }];
Нам также понадобится элемент <svg>
для построения графика.
<svg id="visualisation" width="1000" height="500"></svg>
Далее нам нужно создать наши оси x и y, и для этого нам нужно объявить домен и диапазон. Домен определяет минимальное и максимальное значения, отображаемые на графике, а диапазон — это количество SVG, которое мы будем покрывать. Обе оси должны масштабироваться в соответствии с данными в lineData
, что означает, что мы должны установить домен и диапазон соответственно. Код для рисования осей показан ниже.
var vis = d3.select('#visualisation'), WIDTH = 1000, HEIGHT = 500, MARGINS = { top: 20, right: 20, bottom: 20, left: 50 }, xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) { return dx; }), d3.max(lineData, function(d) { return dx; })]), yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) { return dy; }), d3.max(lineData, function(d) { return dy; })]), xAxis = d3.svg.axis() .scale(xRange) .tickSize(5) .tickSubdivide(true), yAxis = d3.svg.axis() .scale(yRange) .tickSize(5) .orient('left') .tickSubdivide(true); vis.append('svg:g') .attr('class', 'x axis') .attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')') .call(xAxis); vis.append('svg:g') .attr('class', 'y axis') .attr('transform', 'translate(' + (MARGINS.left) + ',0)') .call(yAxis);
В этом коде мы определили WIDTH
, HEIGHT
и MARGINS
для нашего графа. xRange
и yRange
представляют домены для соответствующих осей. Мы устанавливаем диапазон для наших осей согласно левому и правому краям.
Далее, поскольку домен — это данные, которые мы будем показывать на графике, нам нужно получить минимальное и максимальное значения из lineData
. Это делается с использованием d3.max()
и d3.min()
.
Далее мы создали наши оси в соответствии с переменными xRange
и yRange
. Для обеих осей мы определили масштаб как xRange
и yRange
для осей X и Y соответственно. А затем мы просто добавили обе оси к SVG и применили преобразование. Теперь, если мы посмотрим на ось Y, она должна быть ориентирована влево. Следовательно, мы применили левую ориентацию к yAxis
Мы трансформировали обе оси, сохраняя определенные поля в поле зрения, чтобы оси не касались полей SVG.
Вот демонстрация приведенного выше кода, показывающая обе оси.
Затем нам нужно применить xRange
и yRange
к координатам, чтобы преобразовать их в пространство построения и провести линию через пространство построения. Мы будем использовать d3.svg.line()
чтобы нарисовать наш линейный график. Для этого нам нужно создать функцию генератора линий, которая возвращает координаты x и y из наших данных для построения линии. Вот как мы определяем функцию генератора строк:
var lineFunc = d3.svg.line() .x(function(d) { return xRange(dx); }) .y(function(d) { return yRange(dy); }) .interpolate('linear');
Вызов interpolate('linear')
заставляет D3 рисовать прямые линии.
Далее нам нужно установить атрибут d
пути SVG в координатах, возвращаемых функцией line. Это достигается с помощью следующего кода.
vis.append('svg:path') .attr('d', lineFunc(lineData)) .attr('stroke', 'blue') .attr('stroke-width', 2) .attr('fill', 'none');
Мы установили цвет линии с помощью stroke
. Ширина линии определяется с использованием значения stroke-width
. Мы установили fill
на none
, чтобы не заполнять границы графика. Вот демо линейного графа с linear
интерполяцией в действии, и вот то же графическое демо с basis
интерполяцией.
Создание гистограмм
Далее мы рассмотрим создание гистограмм. Так как мы уже создали наши оси, нам не нужно изобретать велосипед. Однако мы немного изменим существующий код. Во-первых, пример данных и кода для создания осей нашей диаграммы:
function InitChart() { var barData = [{ 'x': 1, 'y': 5 }, { 'x': 20, 'y': 20 }, { 'x': 40, 'y': 10 }, { 'x': 60, 'y': 40 }, { 'x': 80, 'y': 5 }, { 'x': 100, 'y': 60 }]; var vis = d3.select('#visualisation'), WIDTH = 1000, HEIGHT = 500, MARGINS = { top: 20, right: 20, bottom: 20, left: 50 }, xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(barData, function(d) { return dx; }), d3.max(barData, function (d) { return dx; }) ]), yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(barData, function(d) { return dy; }), d3.max(barData, function (d) { return dy; }) ]), xAxis = d3.svg.axis() .scale(xRange) .tickSize(5) .tickSubdivide(true), yAxis = d3.svg.axis() .scale(yRange) .tickSize(5) .orient("left") .tickSubdivide(true); vis.append('svg:g') .attr('class', 'x axis') .attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')') .call(xAxis); vis.append('svg:g') .attr('class', 'y axis') .attr('transform', 'translate(' + (MARGINS.left) + ',0)') .call(yAxis); } InitChart();
Вот демонстрация предыдущего кода. Если вы посмотрите на ось Y, масштаб начинается с пяти. Этот минимум взят из наших выборочных данных, где 5 — это минимальное значение Y. Поэтому нам нужно масштабировать ось Y от 0. Для этого нам нужно изменить домен yRange
в функции InitChart()
как показано ниже:
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0, d3.max(barData, function(d) { return dy; })]);
В случае гистограмм мы будем использовать ordinal
шкалы вместо linear
шкал. Порядковые весы помогают поддерживать дискретный домен. Для более подробной информации обратитесь к официальной документации по порядковым шкалам .
Мы также будем использовать rangeRoundBands
чтобы разделить ширину по rangeRoundBands
графика. Мы xRange
используя ordinal
масштаб и rangeRoundBands
как показано ниже. Обратите внимание, что мы также установили расстояние между столбцами на 0,1.
xRange = d3.scale.ordinal().rangeRoundBands([MARGINS.left, WIDTH - MARGINS.right], 0.1).domain(barData.map(function(d) { return dx; }));
Далее нам нужно создать прямоугольные столбцы для данных диаграммы. Мы будем связывать наши образцы данных с прямоугольниками, используя координаты x и y, чтобы установить height
и width
прямоугольных полос. Вот как выглядит код:
vis.selectAll('rect') .data(barData) .enter() .append('rect') .attr('x', function(d) { // sets the x position of the bar return xRange(dx); }) .attr('y', function(d) { // sets the y position of the bar return yRange(dy); }) .attr('width', xRange.rangeBand()) // sets the width of bar .attr('height', function(d) { // sets the height of bar return ((HEIGHT - MARGINS.bottom) - yRange(dy)); }) .attr('fill', 'grey'); // fills the bar with grey color
Вот демонстрация нашей гистограммы в действии.
Добавление событий
Чтобы улучшить интерактивность, мы также можем прикрепить события к барам. Мы можем прикрепить событие, чтобы выделить панель при mouseover
. Вот как это можно сделать:
vis.selectAll('rect') .data(barData) .enter() .append('rect') .attr('x', function(d) { return xRange(dx); }) .attr('y', function(d) { return yRange(dy); }) .attr('width', xRange.rangeBand()) .attr('height', function(d) { return ((HEIGHT - MARGINS.bottom) - yRange(dy)); }) .attr('fill', 'grey') .on('mouseover', function(d) { d3.select(this) .attr('fill', 'blue'); });
В этом коде on('mouseover')
добавляет обработчик событий, который вызывается при наведении курсора мыши, что делает синие столбцы зависания. Вот демонстрация, которая иллюстрирует этот эффект.
Вы можете заметить, что полоски больше не становятся серыми после mouseout
Давайте прикрепим еще одно событие, чтобы вернуть его к предыдущему цвету при наведении мыши. Обновленный код показан ниже:
vis.selectAll('rect') .data(barData) .enter() .append('rect') .attr('x', function(d) { return xRange(dx); }) .attr('y', function(d) { return yRange(dy); }) .attr('width', xRange.rangeBand()) .attr('height', function(d) { return ((HEIGHT - MARGINS.bottom) - yRange(dy)); }) .attr('fill', 'grey') .on('mouseover', function(d) { d3.select(this) .attr('fill', 'blue'); }) .on('mouseout', function(d) { d3.select(this) .attr('fill', 'grey'); });
И вот демонстрация приведенного выше кода в действии.
Вывод
D3.js — это потрясающая библиотека JavaScript для визуализации данных. В этом уроке мы сосредоточились на создании довольно простых гистограмм и линейных диаграмм. Если вы хотите больше экспериментировать, попробуйте добавить дополнительные методы визуализации из библиотеки D3 в диаграммы этой статьи.