Графики. Строим кривые для конвертера валют с Chart.js

5 (100%) 5 vote[s]

На сегодняшний день существует множество графических библиотек на 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 видов графиков:

графики Chart.js
Графики Chart.js

Все они распределены по модулям, поэтому можно подгружать именно тот, который нужен для проекта.

Графики отрисовываются при помощи 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.

Читайте больше по теме:

Подписаться
Уведомление о
guest
0 комментариев
Inline Feedbacks
View all comments
Просмотры: 1201

Популярные записи