На сегодняшний день существует множество графических библиотек на JavaScript для визуализации данных. Это и Chartist.js, и Dygraphs, и гугловский Google Charts, и широко используемый D3.js. Можно ознакомиться с описанием наиболее популярных библиотек здесь. Каждая из библиотек рисует графики с помощью либо HTML5, либо SVG и CSS, либо использует все инструменты. Есть библиотеки с мощным функционалом (D3.js) и массой визуальных эффектов, есть библиотеки попроще (Chart.js), которые идеально подходят для небольших проектов. Есть библиотеки со встроенными графиками, что облегчает и ускоряет работу над проектом, а есть и такие, которые рассчитаны на создание оригинальных проектов и идут без демо.
Возьмем наш конвертер валют (как делать конвертер см.здесь) и попробуем расширить приложение, добавив в него график динамики валют, например, за последнюю неделю. Для наших задач (в контексте изучения canvas) идеально подходит библиотека Chart.js. Вот конечный результат, который у нас получился (кликните по картинке, приложение откроется в новой вкладке):
Графики с Chart.js
В сжатом виде библиотека Chart.js (репозиторий на GitHub) весит всего 11 Кб, предлагает 6 видов графиков:
-
- гистограмма (Bar Chart);
- линейные графики (Line Chart);
- пузырьковая диаграмма (Bubble Chart);
- круговая диаграмма (Pie Chart);
- схема полярной зоны (Polar Area Chart);
- радар диаграмма (Radar Chart).

Все они распределены по модулям, поэтому можно подгружать именно тот, который нужен для проекта.
Графики отрисовываются при помощи HTML5 Canvas. Если в браузере его нет, то используются полифиллы (polyfill – это библиотека, которая добавляет в старые браузеры поддержку возможностей, которые в современных браузерах являются встроенными). Все графики Chart.js интерактивные.
Графики Chart.js доступны под MIT license. Изучить подробно, как работать и подключать библиотеку можно здесь. На этой же странице есть простой пример кода построения гистограммы. Его мы и будем использовать:
<canvas id="myChart" width="400" height="400"></canvas> <script> var ctx = document.getElementById('myChart').getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: true } }] } } }); </script>
Начать работу с Chart.js легко. Достаточно включить в страницу узел <canvas>
для визуализации диаграммы. Теперь нам нужно отредактировать исходный пример:
-
- Мы будем строить линейный график, поэтому в строке 5 меняем type: ‘bar’, на type: ‘line’.
- В строке 7 поле labels: [‘Red’, ‘Blue’, ‘Yellow’, ‘Green’, ‘Purple’, ‘Orange’] очищаем пока, потом вставим туда дни недели.
- Также в строке 10 очищаем поле data: [12, 19, 3, 5, 2, 3], так как мы будем создавать свой массив данных и вставлять его в это поле.
- В строках 11 (backgroundColor:) и 19 (borderColor:) оставляем только первые строки (так как график будет 1).
- В строке 34 убираем отсчет по оси y от 0 (beginAtZero: true) и ставим beginAtZero: false.
Теперь нам нужно сформировать 8 запросов (на 8 дней), создать массивы и вставить их в график.
Ссылка на получение данных по дате имеет такой формат:
https://bank.gov.ua/NBU_Exchange/exchange?date=20191013
Получаем дни недели (сегодняшний и 7 предыдущих) в нужном формате:
Date.prototype.yyyymmdd = function() { var yyyy = this.getFullYear(); var mm = this.getMonth() < 9 ? "0" + (this.getMonth() + 1) : (this.getMonth() + 1); // getMonth() is zero-based var dd = this.getDate() < 10 ? "0" + this.getDate() : this.getDate(); return "".concat(yyyy).concat(mm).concat(dd); }; var d = new Date(); var yesterday = new Date(new Date() - 24*3600*1000); var yesterday1 = new Date(new Date() - 48*3600*1000); var yesterday2 = new Date(new Date() - 72*3600*1000); var yesterday3 = new Date(new Date() - 96*3600*1000); var yesterday4 = new Date(new Date() - 120*3600*1000); var yesterday5 = new Date(new Date() - 144*3600*1000); var yesterday6 = new Date(new Date() - 168*3600*1000); var now = d.yyyymmdd(); var yes = yesterday.yyyymmdd(); var yes1 = yesterday1.yyyymmdd(); var yes2 = yesterday2.yyyymmdd(); var yes3 = yesterday3.yyyymmdd(); var yes4 = yesterday4.yyyymmdd(); var yes5 = yesterday5.yyyymmdd(); var yes6 = yesterday6.yyyymmdd();
Будем использовать jQuery. Формируем запрос на текущий курс для вставки в форму конвертера валют:
var course = 0; $.ajax({ type: 'get', url: 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange', dataType: 'xml', success: function(response) { $(response).find("currency").each(function(i,elem) { if($(elem).find('cc').text() == 'USD') { course = +$(elem).find('rate').text(); } if($(elem).find('cc').text() == 'EUR') { course1 = +$(elem).find('rate').text(); } if($(elem).find('cc').text() == 'RUB') { course2 = +$(elem).find('rate').text(); } if($(elem).find('cc').text() == 'XAU') { course3 = +$(elem).find('rate').text(); } { data = $(elem).find('exchangedate').text(); } }) } });
Далее формируем 8 запросов (в итоговом приложении их 10) для получения данных на дни недели, включая сегодняшний:
var course221 = 0; $.ajax({ type: 'get', url: `https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=${now}`,//меняем ${now} на ${yes}, ${yes1} и т.д.и присваиваем новые значения course для каждого дня, например course31, ...32, ...33, course41, ...42 и т.д. dataType: 'xml', success: function(response) { $(response).find("currency").each(function(i,elem) { if($(elem).find('cc').text() == 'USD') { course221 = +$(elem).find('rate').text(); } if($(elem).find('cc').text() == 'EUR') { course222 = +$(elem).find('rate').text(); } if($(elem).find('cc').text() == 'RUB') { course223 = +$(elem).find('rate').text(); } if($(elem).find('cc').text() == 'XAU') { course224 = +$(elem).find('rate').text(); } }) } });
Далее создаем из полученных данных массивы (8 шт.):
var d = new Array(8); d[0] = course71; d[1] = course61; d[2] = course51; d[3] = course41; d[4] = course31; d[5] = course25; d[6] = course21; d[7] = course221; var d2 = new Array(8); d2[0] = course72; d2[1] = course62; d2[2] = course52; d2[3] = course42; d2[4] = course32; d2[5] = course26; d2[6] = course22; d2[7] = course222;//и так далее...
Затем вставляем наши дни недели и данные курса в графики (их всего будет 4 шт):
var ctx = document.getElementById('myChart').getContext('2d'); var myChart = new Chart(ctx, { type: 'line', data: { labels: [yest6, yest5, yest4, yest3, yest2, yest1, yest, wt], datasets: [{ label: 'USD', data: d, backgroundColor: [ 'rgba(255, 99, 132, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: false } }] } } }); var ctx = document.getElementById('myChart2').getContext('2d'); var myChart2 = new Chart(ctx, { type: 'line', data: { labels: [yest6, yest5, yest4, yest3, yest2, yest1, yest, wt], datasets: [{ label: 'EUR', data: d2, backgroundColor: [ 'rgba(80, 99, 132, 0.2)' ], borderColor: [ 'rgba(55, 99, 132, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: false } }] } } }); var ctx = document.getElementById('myChart3').getContext('2d'); var myChart3 = new Chart(ctx, { type: 'line', data: { labels: [yest6, yest5, yest4, yest3, yest2, yest1, yest, wt], datasets: [{ label: 'RUB', data: d3, backgroundColor: [ 'rgba(25, 9, 232, 0.2)' ], borderColor: [ 'rgba(25, 9, 232, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: false } }] } } }); var ctx = document.getElementById('myChart4').getContext('2d'); var myChart4 = new Chart(ctx, { type: 'line', data: { labels: [yest6, yest5, yest4, yest3, yest2, yest1, yest, wt], datasets: [{ label: 'XAU 1 тр. унция', data: d4, backgroundColor: [ 'rgba(200, 199, 132, 0.2)' ], borderColor: [ 'rgba(100, 99, 32, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: false } }] } } });
Массивы и графики вставляем в showChart(), которую подключаем к событию загрузки body (onload=»showChart();myFunction();»). Функция myFunction() вставляет исходные данные в форму конвертера, а функция showChart рисует графики, используя отдельные данные. Такое разделение необходимо из-за особенности работы сервера: с 16.00 в течение 1.5 часа поступают только данные курса доллара, и скрипт построения графиков в это время не будет работать (если они будут в одной функции onload с данными формы). А при разделении графики работают автономно.
В этом примере используется только Chart.min.js. Чтобы не загружать его на сервер, можно подключить так:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
Это были основные моменты, как добавить в приложение графики для визуализации данных. Полный исходник приложения с прогнозом погоды, проверкой IP можно скачать здесь.
В качестве бонуса — конвертер с выводом курса НБУ 20 валют с изображениями флагов стран, наличный обмен USD, EUR, RUB в ПриватБанке. В дополнение — три обновляемых графика с динамикой за последний месяц, комбинированный график-гистограмма и статичный график ежедневной динамики USD за последние 3 года.
В этом примере просто делается больше запросов, добавляется таймаут. Для статичного графика загружается необновляемый JSON-файл, парсится в массив и вставляется в график:
//объявляем функцию, вставляем данные unction showChart2(){ var jsonString = '[{...}]'; //получаем из JSON массив var obj = JSON.parse(jsonString); //перебираем массив, создаём 2 новых var arr = []; for (var i=0; i<=obj.length-1; i++) { arr.push(obj[i].USD); }; var arr1 = []; for (var i=0; i<=obj.length-1; i++) { arr1.push(obj[i].date); }; // arr (курс) и arr1 (дата)- наши массивы, которые вставляем в график
Просмотреть код можно будет в браузере, нажав комбинацию клавиш Ctrl+U.
Читайте больше по теме: