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

Гистограмма является очень простым, но мощным способом представления данных в случаях, когда нужно сравнить значения. В этом руководстве вы научитесь создавать разные их виды – простые, групповые, стековые и 100% стековые гистограммы, а также эффективно кастомизировать их с помощью всего нескольких строк JS-кода.

Будучи любителем крикета, я внимательно следила за чемпионатом мира ICC T20 2022 среди мужчин, проходившим осенью в Австралии, и в итоге решила взять данные для иллюстраций именно с него. Гистограммы, которые мы построим в ходе этого урока, позволят оценить статистику отбиваний мяча, а конкретно количество очков, заработанных десятью ведущими отбивающими в рамках турнира. Начнём!

1. Базовая гистограмма в JS


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

  1. Создание контейнера.
  2. Внесение файлов скриптов.
  3. Подготовка данных.
  4. Написание кода для визуализации.

▍ 1.1 Создание контейнера


Первым делом нужно настроить место для гистограммы.

Если у вас уже есть веб-страница, куда вы хотите её поместить, то просто откройте свой HTML-файл. Если же таковой нет, создайте. После этого добавьте в неё блочный HTML-элемент и присвойте ему ID. Также установите его ширину, высоту и прочие параметры стилизации, согласно вашим нуждам.

Я создала простейшую HTML-страницу, добавила элемент <div> с ID «контейнера» и установила его ширину/высоту равными 100%, чтобы итоговая гистограмма заполнила всю страницу:

<html>
  <head>
    <title>JavaScript Column Chart</title>
    <style type="text/css">      
      html, body, #container { 
        width: 100%; height: 100%; margin: 0; padding: 0; 
      } 
    </style>
  </head>
  <body>
    <div id="container"></div>
  </body>
</html>

▍ 1.2 Внесение файлов скриптов


Самый простой способ быстро создать интерактивную гистограмму для веба – это использовать одну из существующих библиотек JavaScript (англ.). Эти библиотеки представляют наборы готового кода для генерации диаграмм, что позволяет визуализировать данные (англ.) путём минимальных усилий.

Этапы создания гистограммы во всех библиотеках, по сути, остаются одинаковыми. Какую бы вы ни выбрали, добавьте её к веб-странице, указав соответствующие JS-файлы в теге <script> раздела <head>. После этого добавьте ещё один тег <script> в любом месте раздела <head> или <body> — здесь будет размещён код для построения гистограммы.

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

<html>
  <head>
    <title>JavaScript Column Chart</title>
    <style type="text/css">      
      html, body, #container { 
        width: 100%; height: 100%; margin: 0; padding: 0; 
      } 
    </style>
  </head>
  <body>  
    <div id="container"></div>
  </body>
</html>

▍ 1.3 Подготовка данных


Далее нужно подготовить данные, которые вы хотите визуализировать.

Я взяла статистику по набору очков десятью ведущими бэтсменами (отбивающий мяч игрок) на упомянутом чемпионате по крикету с сайта ESPNcricinfo и сопоставила итоговые показатели этих бэтсменов в простом многомерном массиве. Естественно, вы можете использовать другой формат данных вроде JSON, XML, CSV и т. д.

[
  ["Virat Kohli", "296", "India"],
  ["Max O'Dowd", "242", "Netherlands"],
  ["Suryakumar Yadav", "239", "India"],
  ["JD Butler", "225", "England"],
  ["Kusal Mendis", "223", "Sri Lanka"],
  ["Sikandar Raza", "219", "Zimbabwe"],
  ["Pathum Nissanka", "214", "Sri Lanka"],
  ["AD Hales", "212", "England"],
  ["Lorkan Tucker", "204", "Ireland"],
  ["Glenn Phillips", "201", "New Zealand"]
]

▍ 1.4 Написание кода для визуализации


Поле организовано, игроки готовы, жребий брошен – настало время начинать матч! Создание гистограммы с помощью подходящей библиотеки JS (англ.) подобно выбиванию шести очков в крикете – максимальная отдача при минимуме усилий. Ниже я покажу, как можно всё реализовать буквально в нескольких строках кода.

Первым делом я добавляю функцию anychart.onDocumentReady() в тег <script> раздела <body>. Всё остальное будет помещаться в эту функцию.

<script>
  anychart.onDocumentReady(function() {
    // Далее пойдёт код для создания гистограммы
  });
</script>

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

// Создание гистограммы
var chart = anychart.column();

// Создание набора данных
var series = chart.column([
  ["Virat Kohli", "296", "India"],
  ["Max O'Dowd", "242", "Netherlands"],
  ["Suryakumar Yadav", "239", "India"],
  ["JD Butler", "225", "England"],
  ["Kusal Mendis", "223", "Sri Lanka"],
  ["Sikandar Raza", "219", "Zimbabwe"],
  ["Pathum Nissanka", "214", "Sri Lanka"],
  ["AD Hales", "212", "England"],
  ["Lorkan Tucker", "204", "Ireland"],
  ["Glenn Phillips", "201", "New Zealand"]
]);

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

// Добавление подписей к осям
chart.xAxis().title("Batsman");
chart.yAxis().title("Number of runs");

// Добавление подписи к графику
chart.title("Top 10 Run Scorers at ICC Men's T20 World Cup 2022");

В последнюю очередь я настраиваю элемент контейнера – здесь потребуется его ID – и отображаю итоговую гистограмму.

// Настройка элемента контейнера
chart.container("container");

// Отображение гистограммы
chart.draw();

Вот как выглядит весь код JS в теге <script>:

anychart.onDocumentReady(function () {

  // Создание гистограммы
  var chart = anychart.column();

  // Создание набора данных
  var series = chart.column([
    ["Virat Kohli", "296", "India"],
    ["Max O'Dowd", "242", "Netherlands"],
    ["Suryakumar Yadav", "239", "India"],
    ["JD Butler", "225", "England"],
    ["Kusal Mendis", "223", "Sri Lanka"],
    ["Sikandar Raza", "219", "Zimbabwe"],
    ["Pathum Nissanka", "214", "Sri Lanka"],
    ["AD Hales", "212", "England"],
    ["Lorkan Tucker", "204", "Ireland"],
    ["Glenn Phillips", "201", "New Zealand"]
  ]);

  // Добавление подписей к осям
  chart.xAxis().title("Batsman");
  chart.yAxis().title("Number of runs");

  // Добавление подписи к графику
  chart.title("Top 10 Run Scorers at ICC Men's T20 World Cup 2022");

  // Настройка элемента контейнера
  chart.container("container");

  // Отображение гистограммы
  chart.draw();

});

▍ Результат 1: базовая гистограмма


Вуаля! Простая и функциональная гистограмма готова! Её интерактивная версия вместе с исходным кодом доступна на Playground.


Гистограммы помогают нам проводить сравнение. В нашем случае она показывает, что Virat Kohli прилично вырвался по очкам при том, что между остальными игроками разрыв оказался небольшим.

Но это только начало. Теперь мне также интересно узнать, каким образом каждый из игроков заработал все свои очки. Говоря конкретнее, я хочу выяснить, сколько очков из общего количества было набрано за счёт 6-, 4-очковых ударов, а также путём успешного пробегания до противоположного края питча. Эту информацию можно полноценно отразить с помощью группированной или стековой гистограммы. Далее я продемонстрирую вам, как создавать ту и другую, сопроводив их прекрасной визуализацией.

2. Базовая группированная гистограмма


Группированную гистограмму, как и её простой вариант, с помощью JS можно создать быстро и непринуждённо. По факту основа здесь остаётся той же, и вам достаточно просто поменять данные.

▍ Добавление разных свойств данных


Вместо общих значений мы внесём в гистограмму количество очков, заработанных каждым из 10 ведущих бэтсменов путём 6-, 4-очковых ударов и перебежек до противоположного края питча. Эти данные я взяла с уже упомянутого ресурса ESPNcricinfo и организовала их в датасет:

var dataSet = anychart.data.set([
  ["Virat Kohli", "India", "148", "100", "48"],
  ["Max O'Dowd", "Netherlands", "106", "88", "48"],
  ["Suryakumar Yadav", "India", "81", "104", "54"],
  ["JD Butler", "England", "87", "96", "42"],
  ["Kusal Mendis", "Sri Lanka", "95", "68", "60"],
  ["Sikandar Raza", "Zimbabwe", "89", "64", "66"],
  ["Pathum Nissanka", "Sri Lanka", "114", "52", "48"],
  ["AD Hales", "England", "76", "76", "60"],
  ["Lorkan Tucker", "Ireland", "104", "76", "24"],
  ["Glenn Phillips", "New Zealand", "77", "76", "48"]
]);

▍ Сопоставление данных


Далее необходимо сопоставить эти данные с тремя группами, каждая из которых отражает свойство. Первая группа отражает очки, заработанные путём пробегания до противоположного края питча. Вторая показывает очки, полученные путём 4-очковых ударов, а третья — очки, заработанные 6-очковыми ударами.

var firstSeriesData = dataSet.mapAs({x: 0, value: 4});
var secondSeriesData = dataSet.mapAs({x: 0, value: 3});
var thirdSeriesData = dataSet.mapAs({x: 0, value: 2});

▍ Создание групп


Теперь можно создать три группы с соответствующими им данными.

var series;
series = chart.column(firstSeriesData);
series = chart.column(secondSeriesData);
series = chart.column(thirdSeriesData);

▍ Результат 2: группированная гистограмма


Базовая группированная гистограмма готова! Её интерактивную версию вместе с исходным кодом можно найти на Playground.


Группированная гистограмма прекрасно отражает разделение заработанных очков по свойствам каждой категории (то есть каждого игрока). Однако нам также интересно видеть и общие показатели игроков, так что теперь мы создадим стековую гистограмму.

3. Базовая стековая гистограмма


Чтобы превратить столбцы группированной гистограммы в стековое представление, потребуется всего одна короткая строчка JS-кода.

▍ Установка режима стекинга значений


Активируем режим стекинга значений по оси Y.

chart.yScale().stackMode("value");

▍ Результат 3: стековая гистограмма


Готово! Теперь у нас есть базовая стековая гистограмма. Её интерактивная версия вместе с исходным кодом доступна на Playground.


А теперь давайте её украсим!

4. Кастомизация стековой гистограммы


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

▍ Корректировка свойств


При наведении курсора на один из сегментов интерактивного столбца всплывающая подсказка автоматически показывает значения отражаемого им свойства. Но какое из них к чему относится? Давайте проименуем свойства, чтобы всё стало понятно.

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

Для этого я создам функцию, которая будет получать каждое свойство, его название и связанный с ним цвет. Кроме того, я добавлю в эту функцию атрибут перехода (stroke), который будет применяться к каждому свойству, делая между ними небольшой отступ.

var setupSeries = function (series, name, color) {
  series.name(name).stroke("2 #fff 1").fill(color);
};

Теперь я настрою три свойства с помощью только что созданной функции и присвою каждому из них соответствующее название и цвет.

// Сохранение свойств
var series;

// Создание первого свойства с помощью функции
series = chart.column(firstSeriesData);
setupSeries(series, "Runs scored with Sixes", "#eb2362");

// Создание второго свойства с помощью функции
series = chart.column(secondSeriesData);
setupSeries(series, "Runs scored with Fours", "#00b1e5");

// Создание третьего свойства с помощью функции
series = chart.column(thirdSeriesData);
setupSeries(series, "Running between the wickets", "#0f0449");

▍ Добавление легенды


Чтобы ещё больше повысить читаемость этой гистограммы, будет нелишним добавить легенду, которая покажет, какой цвет и к какому свойству относится. Это легко сделать, просто включив опцию легенды. Я скорректирую лишь размер шрифта и отступы.

chart.legend().enabled(true).fontSize(14).padding([10, 0, 0, 0]);

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

▍ Проработка подписей, всплывающей подсказки и заголовка


Как видите, некоторые имена игроков на оси X не видны. Чтобы это исправить, я поверну их подписи.

chart.xAxis().labels().rotation(-90);

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

chart.tooltip().titleFormat(function () {
  return this.x + " — " + this.points[0].getStat("categoryYSum");
});

Кроме того, можно отображать в подсказке значения всех свойств вместе, используя режим объединения (union).

chart.tooltip().displayMode("union");

Наконец, мы немного увеличим заголовок гистограммы, изменим цвет его шрифта и добавим отступы.

chart.title().fontSize(20).fontColor("#2b2b2b").padding([5, 0, 0, 0]);

▍ Результат 4: стековая гистограмма после кастомизации


Вот и всё! Наша стековая гистограмма кастомизирована. Взгляните, насколько красивой и информативной она стала! Также оцените её интерактивное представление на Playground, где вы можете дополнительно поиграться с кодом, внести собственные данные и так далее.


Выглядит симпатично, не так ли? И тут мы отчётливо видим не только общие очки игроков, но и то, что некоторые заработали их путём усердных пробежек, в то время как другие – за счёт более удачных отбиваний.

5. 100% стековая гистограмма


В завершение я хочу продемонстрировать вам создание 100% стековой гистограммы, которая поможет упростить сравнение отдельных свойств по всем точкам данных.

▍ Переключение режима стекинга столбцов


Чтобы получить представление столбчатой гистограммы в виде процентов, нужно лишь изменить режим стекинга с value на percent.

chart.yScale().stackMode("percent");

▍ Результат 5: 100% стековая гистограмма


Готово. Перед вами последний пример визуализации данных в этом руководстве. Также приглашаю оценить его интерактивную версию вместе с исходным кодом на Playground.


Заключение


В этом руководстве я показала, как создавать столбчатые диаграммы с помощью JavaScript (HTML) в разных вариациях: простые, групповые, стековые и 100% стековые. При этом вы также узнали, как их можно кастомизировать.

Здесь я использовала JS-библиотеку для построения диаграмм под названием AnyChart, однако существует и много других с аналогичными возможностями. Хорошо то, что в своей основе сам процесс построения диаграмм в подобных библиотеках похож, так что вы без проблем сможете применить полученные знания при использовании любой из них.

Желаю вам успеха в создании других красивых гистограмм и прочих визуализаций данных!

Играй в нашу новую игру прямо в Telegram!

Комментарии (9)


  1. little-brother
    20.01.2023 16:20
    +6

    Неплохо бы вначале "от переводчика" указать, что продукт AnyChart платный и изменить название на что-нибудь вида "Создание столбчатых диаграмм с помощью JavaScript и AnyChart". Приписка в конце статьи выглядит как отмазка - все либы для графиков похожи, можете использовать все что хотите (но я буду использовать платный продукт).


    1. Bright_Translate Автор
      20.01.2023 16:34

      В тексте при первом упоминании этой библиотеки автор явно указывает, что она платна только для коммерческого использования. Это вполне поясняет суть. К тому же не приписка, а пояснение о возможности по представленной в статье методике использовать и другие библиотеки, указано дважды. Изначально там же, где представлена AnyChart, а затем еще раз в конце, как вы и заметили. Дополнительно указывать эту библиотеку в названии тоже повода не вижу.


  1. Hidadmin
    20.01.2023 16:34
    +8

    Я использую бесплатный JQPlot - http://www.jqplot.com/examples/ - куча всевозможных вариантов графиков и диаграмм.
    А вашей статье место в Яндекс Дзене, а не на Хабре


    1. vasyakolobok77
      21.01.2023 11:20

      JQuery бибилиотека в 2023 году "такое себе" решение. Highcharts для некоммерческого использования наше все.


  1. savostin
    20.01.2023 21:46
    +4

    Было бы интересно, если бы хотя бы с D3.js, хотя и таких туча.


  1. Xtray
    20.01.2023 23:37


    1. Bright_Translate Автор
      21.01.2023 08:16

      Благодарю, исправил.


  1. Dolios
    21.01.2023 11:35
    +1

    D3.js


    Вот примеры столбчатых диаграмм. Они кликабельнные, с исходниками.


  1. dlinyj
    21.01.2023 15:42
    +2

    В статье Осциллограф в браузере использовал библиотеку Chart.js.

    Даже я, человек далёкий от js и веба разобрался и налабал простой пример. Но, как я понимаю, примеров таких библиотек — тысячи.