Статьи

Создание компонента диаграммы с помощью Angular 2 и FusionCharts

Эта статья была рецензирована Vildan Softic . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

Как веб-разработчик, если есть что-то, что вы не можете пропустить, это Angular 2 . Это полное переписывание популярного JavaScript-фреймворка от Google, и оно постоянно в новостях по всем правильным причинам. Он предлагает некоторые значительные улучшения по сравнению с предыдущими версиями, и поэтому мы выбираем его сегодня, чтобы создать несколько красивых графиков.

Для диаграмм мы будем использовать библиотеку диаграмм JavaScript, предоставленную FusionCharts . Он предлагает хорошую коллекцию диаграмм и совместим со всеми основными браузерами. Хотя FusionCharts предлагает специальный плагин для Angular , он еще не совместим с Angular 2. Поэтому я не собираюсь его использовать, а вместо этого пишу код напрямую, используя JavaScript и Angular 2. ( Примечание: рекомендуется использовать плагин, если вы используете Угловой 1 в вашем приложении ).

График, который мы собираемся построить, будет отображать интересную статистику — доход пяти ведущих технологических компаний (Amazon, Apple, Facebook, Google и Microsoft) и будет иметь возможность переключаться между данными о доходах за 2014 и 2015 годы. Сначала мы пойдем пошаговый процесс создания диаграмм в Angular 2. После создания базовой диаграммы мы рассмотрим некоторые сложные темы, такие как добавление аннотаций и обновление данных диаграммы.

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

Угловой 2 против Угловой 1.x

Angular 2 имеет некоторые существенные изменения по сравнению с предыдущей основной версией (Angular 1.x), например, его поддержка таких языков, как TypeScript и Dart, и способ вычисления обновлений DOM. Если вы хотите узнать больше о том, как концепции и методы Angular 1 соответствуют Angular 2, вы можете ознакомиться с официальным кратким справочником . Если вы заинтересованы в переносе своего приложения с Angular 1.x на Angular 2, вы можете прочитать официальное руководство по миграции .

Хотя Angular 2 поддерживает TypeScript и Dart, мы будем использовать собственный JavaScript для написания приложения Angular 2 в этом учебном пособии из-за его привычного знакомства. Использование TypeScript или Dart также приведет к ненужному этапу сборки.

Настроить

Есть несколько способов начать работу с проектом Angular 2. Проще всего, возможно, зайти на официальный сайт и следовать их 5-минутному учебному пособию по быстрому старту .

Однако одно небольшое предостережение для этого подхода заключается в том, что он основан на том, что на вашей машине установлены Node и npm. У нас есть руководство для этого , но если вы предпочитаете следовать этому руководству, не устанавливая его, вы можете использовать следующий шаблон:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Angular 2 FusionCharts Demo</title>

    <!-- 1. Load custom CSS & fonts-->
    <link rel="stylesheet" href="styles.css">
    <link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300' rel='stylesheet'>

    <!-- 2. Load Angular 2 specific libraries -->
    <script src="https://code.angularjs.org/2.0.0-beta.17/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.17/Rx.umd.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.17/angular2-all.umd.dev.js"></script>

    <!-- 3. Load FusionCharts library-->
    <script src="https://static.fusioncharts.com/code/latest/fusioncharts.js"></script>

    <!-- 4. Load component -->
    <script src='main.js'></script>
  </head>
  <body>

    <!-- 5. Display the application -->
    <angular-chart>Loading...</angular-chart>
  </body>
</html>

Создание компонента диаграммы

Компоненты являются строительными блоками любого приложения Angular 2. Это многократно используемые фрагменты кода, состоящие из представления и некоторой логики. Если вы знакомы с Angular 1, вы можете думать о них как о директивах с шаблоном и контроллером.

Вот основа нашего компонента диаграммы:

 (function(chartApp){
  chartApp.AppComponent = ng.core.Component({
    selector: 'angular-chart',
    template: '<div>Chart will render here</div>'
  }).Class({
    constructor: function(){}
  });

  document.addEventListener('DOMContentLoaded', function() {
    ng.platform.browser.bootstrap(chartApp.AppComponent);
  });
})(window.chartApp || (window.chartApp = {}));

Давайте на секунду посмотрим, что происходит.

Мы начнем с IIFE ( немедленно вызванного выражения функции ), которое мы используем для пространства имен нашего приложения. Мы передаем его window.chartApp Вот где будет жить наше приложение — в одном свойстве глобального объекта.

Внутри IIFE мы создаем наш компонент ( AppComponentng.coreComponent и Class из Component Мы передаем методу selector

  • template Angular будет создавать и отображать экземпляр компонента всякий раз, когда он встречает HTML-элемент, соответствующий этому селектору.

  • <div> В настоящее время мы передаем строку, содержащую элемент-заполнитель Class

Метод type

Определив наш базовый компонент, мы инициализируем его с помощью функции начальной загрузки браузера Angular.

На этом этапе вы сможете запустить код в своем браузере и увидеть сообщение «Диаграмма будет отображаться здесь».

Создание диаграммы

Давайте перейдем к созданию диаграммы и отображению некоторых данных за 2014 год.

Для этого нам нужно использовать функцию конструктора FusionCharts, в которую мы передаем объект, содержащий все параметры конфигурации для экземпляра диаграммы:

  • renderAt
  • width
  • heightid
  • dataFormat
  • dataSourcedataSource
  • new FusionCharts({
    "type": "column2d",
    "renderAt": "chart-container",
    "width": "550",
    "height": "400",
    "id": "revenue-chart",
    "dataFormat": "json",
    "dataSource": {
    "chart": {
    "yAxisName": "Revenue (In USD Billion)",
    "yAxisMaxValue": "200",
    ...
    },
    "data": [{
    "label": "Amazon",
    "value": "88.99"
    }, {
    "label": "Apple",
    "value": "182.8"
    }
    ...
    ]
    }
    });
 chart

Вот полный файл конфигурации .

Если вы не уверены в том, что на самом деле делает какой-либо из параметров templateАтрибуты диаграммы» в документации FusionCharts.

Еще одна вещь, которую мы должны сделать, это обновить наш шаблон, включив в него контейнер, который должен отображать наш график. Вы можете сделать это, указав строку в свойстве templateUrlchartApp.AppComponent = ng.core.Component({
selector: 'angular-chart',
templateUrl: 'chart.html'
}).Class({
...
});

 <div class="container">
  <h1>Revenue of Top Tech Companies (2014)</h1>
  <div id ="chart-container"></div>
</div>

В любом случае, так должен выглядеть наш шаблон.

 main.js

Вот демонстрация того, что мы имеем до сих пор:

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

Если вы перейдете к демонстрационной версии Plunker, в файле chartAppкласс HTTP Angular . Это сделано для ясности (это облегчает отслеживание кода, специфичного для Angular), а также потому, что выполнение запроса данных — это то, что вы обычно делаете в реальном сценарии.

Однако это не является абсолютно необходимым, и вы получите тот же результат, если будете делать все прямо в конструкторе (function(chartApp) {
chartApp.AppComponent = ng.core.Component({
selector: 'angular-chart',
template: '<div class="container"><h1>Revenue of Top Tech Companies (2014)</h1><div id ="chart-container"></div></div>'
}).Class({
constructor: function() {
FusionCharts.ready(function(){
var revenueChart = new FusionCharts({
// config data here
}).render();
});
}
});

document.addEventListener(‘DOMContentLoaded’, function() {
ng.platform.browser.bootstrap(chartApp.AppComponent);
});
})(window.chartApp || (window.chartApp = {}));

 FusionCharts.ready

Единственное, что следует упомянуть, это то, что код инициализации обернут в метод $dataset.0.set.1.endX Это защищает код создания экземпляра диаграммы от вызова до загрузки библиотеки FusionCharts.

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

Добавление аннотаций

Для добавления логотипов компании к оси x мы будем использовать одну из мощных функций FusionCharts — аннотации . Аннотации к объекту FusionCharts позволяют рисовать пользовательские фигуры или изображения в назначенных местах на диаграмме.

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

Все становится интересным, когда вы используете динамические аннотации, например, для получения информации о позициях, которые зависят от данных диаграммы. Представьте, что вы хотите нарисовать что-то точно там, где заканчивается столбец. Вы можете использовать макрос динамической аннотации $dataset.0.set.1.endY"showLabels": "0" Вы можете узнать больше о аннотациях и о том, как их использовать, на этой странице документации FusionCharts .

Для нашей диаграммы мы будем использовать макросы динамической аннотации, чтобы получить начальную и конечную координаты каждого столбца, где мы будем рисовать соответствующие логотипы компании. Мы также отключим стандартные метки оси X, используя атрибут диаграммы {
"type": "column2d",
...
"dataSource": {
"chart": {
"showLabels": "0",
...
},
"data": [{ ... }],
"annotations": {
"groups": [{
"id": "logo-images",
"xScale": "30",
"yScale": "30",
"showBelow": "0",
"items": [{
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735364amazon.jpg",
"x": "$dataset.0.set.0.startx + 25",
"y": "$dataset.0.set.0.endY + 10"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735362apple.jpg",
"x": "$dataset.0.set.1.startx + 85",
"y": "$dataset.0.set.1.endY + 10"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735369facebook.jpg",
"x": "$dataset.0.set.2.startx + 20",
"y": "$dataset.0.set.2.endY + 10"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735358google.jpg",
"x": "$dataset.0.set.3.startx + 5",
"y": "$dataset.0.set.3.endY + 5"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735372microsoft.jpg",
"x": "$dataset.0.set.4.startx + 30",
"y": "$dataset.0.set.4.endY + 10"
}]
}]
}
}
}

Для достижения вышеуказанных целей добавьте следующий код в конфигурацию диаграммы:

 type

В приведенном выше коде:

  • url
  • x
  • ydata

После добавления приведенного выше кода вы должны увидеть логотипы компаний, отображаемые на оси X. Чтобы узнать больше об использовании аннотаций и о том, что еще возможно, пожалуйста, обратитесь к странице документации (упомянутой выше).

Переключение между наборами данных

Последнее, что мы хотим реализовать, — это позволить пользователю переключаться между годами, видя другой набор данных в зависимости от выбранного года (2014 или 2015).

Структурирование данных.

Поэтому нам нужно подумать о том, как структурировать наши данные таким образом, чтобы мы могли определять разные наборы данных для разных лет. Как упоминалось ранее, FusionCharts ожидает, что параметры конфигурации будут содержать свойство {
"type": "column2d",
...
"dataSource": {
"chart": {},
"data": [
{
"label": "whatever",
"value": "a value"
}
]
}
}

 dataSet

Одним из способов обработки нескольких наборов данных было бы определение объекта var chartComp= this;
chartComp.dataSet = {
"2014": [{
"label": "Amazon",
"value": "88.99"
}, {
"label": "Apple",
"value": "182.8"
}, {
"label": "Facebook",
"value": "12.47"
}, {
"label": "Google",
"value": "65.67"
}, {
"label": "Microsoft",
"value": "86.83"
}],
"2015": [{
"label": "Amazon",
"value": "107.01"
}, {
"label": "Apple",
"value": "233.72"
}, {
"label": "Facebook",
"value": "17.93"
}, {
"label": "Google",
"value": "74.54"
}, {
"label": "Microsoft",
"value": "93.58"
}]
}

 "data": chartComp.dataSet['2014'],

Затем в опциях конфигурации мы переходим к конструктору FusionCharts, мы можем сделать:

 <div class="container">
  <h1>Revenue of Top Tech-companies</h1>

  <div class="actions">
    <button (click)="yearChange(2014)"
            [ngClass] = "{selected: selectedYear== 2014}">2014
    </button>
    <button (click)="yearChange(2015)"
            [ngClass] = "{selected: selectedYear== 2015}">2015
    </button>
  </div>
  <div id ="chart-container"></div>
</div>

Обновление данных диаграммы при переключении

Мы также хотим, чтобы график обновлялся данными за 2015 год, как только кто-то нажмет кнопку 2015 года и вернется к отображению данных за 2014 год, когда нажата кнопка 2014 года .

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

 ngClass

Обратите внимание на новый синтаксис для добавления прослушивателя событий и добавления директивы ngClass в Angular 2. Они почти такие же, как Angular 1, за исключением некоторых скобок и скобок.

Я добавил директиву selectedselectedYear Это основано на свойстве chartComp.selectedYear = 2014;

Мы можем установить текущий выбранный год на 2014, когда компонент рендерится, добавив следующую строку в верхнюю часть конструктора:

 yearChange

Логика для обработки нажатий кнопок будет добавлена ​​в новую функцию .Class({
constructor: function(){ ... },
yearChange: function(){ // button logic here }
);

 getChartData

Для этого мы будем использовать метод setChartData FusionChart, который требует как параметров конфигурации диаграммы, так и фактических данных диаграммы. Вместо того, чтобы сначала сохранять атрибуты диаграммы, а затем ссылаться на них, мы получим атрибуты диаграммы из уже отрисованной диаграммы, используя метод yearChange: function(year) {
var revenueChart = FusionCharts.items['revenue-chart'];
var chartJson = revenueChart.getChartData('json');
chartJson.data = this.dataSet[year];
revenueChart.setChartData(chartJson);
this.selectedYear = year;
}

 dataSet

После добавления HTML-кода для кнопок и вышеупомянутого обработчика нажатия для этих кнопок, нажатие на эти кнопки должно загрузить данные за год для диаграммы.

демонстрация

И вот последняя демонстрация.

Вы можете просмотреть код для этой демонстрации на Plunker . Или вы можете скачать код из нашего репозитория GitHub .

Если вы перейдете к Plunker, вы увидите, что мы непосредственно определили свойство dataSet в файле config.json . Это делает вещи намного аккуратнее в нашем компоненте.

Заключение и последующие шаги

Мы начали с создания простой угловой диаграммы, а затем добавили к ней больше функциональности, используя аннотации и другие API FusionCharts. Но это только вершина айсберга, и многое другое можно сделать с помощью Angular 2 и FusionCharts. Некоторые вещи, которые вы можете изучить самостоятельно:

  • Включите больше диаграмм. Столбчатая диаграмма — не всегда лучший способ представления набора данных. В зависимости от вашего варианта использования вы можете использовать разные диаграммы, такие как водопад, радар, манометр и т. Д. Поэтому попробуйте использовать процесс, описанный в этом руководстве, чтобы построить другую диаграмму и посмотреть, сможете ли вы сделать это успешно.

  • Включите диаграммы в свое приложение. Если вы занимаетесь созданием гибридных мобильных приложений, вы должны знать, что Ionic 2 (последняя версия Ionic) основана на Angular 2. И это хорошая новость, поскольку вы можете использовать это руководство в качестве основы для создавать диаграммы для ваших приложений Ionic, а также.

  • Узнайте больше о событиях: в этом руководстве я объяснил, как использовать метод setChartDataсобытий и методов , которые можно использовать для улучшения взаимодействия с пользователем вашего приложения. Посетите вышеуказанные ссылки, чтобы узнать больше о различных событиях и методах, предлагаемых FusionCharts.

Если вы столкнулись с какими-либо трудностями при попытке составить диаграммы самостоятельно, обратитесь к документации Angular или FusionCharts (в зависимости от проблемы) или просто оставьте комментарий ниже. Я буду более чем рад помочь!