
Многие думают об Angular только как об HTML-компонентах и формах. В конце концов, Angular1 был безумно простым и классным для создания форм с двусторонним связыванием. Но что, если бы мы взяли все те же потрясающие концепции компонентов и использовали их для создания потрясающих визуализаций? Сегодня есть несколько различных способов визуализации диаграмм в браузере; SVG, Canvas и WebGL. В этой статье я собираюсь поговорить о построении диаграмм, управляемых SVG, эта конкретная диаграмма ДЕЙСТВИТЕЛЬНО замечательно работает с такими фреймворками, как Angular, потому что, в конце концов, SVG выражается через DOM.
Недавно у меня была возможность открыть исходный код проекта, над которым я работал много лет, и когда мы выпустили его, мы переписали его на Angular2. Это потрясающий фреймворк под названием ngx-charts, если вы еще не проверили его, я настоятельно рекомендую, но я могу быть предвзятым; P. Сначала мы не собирались создавать полноценный фреймворк для построения графиков, но я знаю, что это происходит со временем :)! Недавно у нас была возможность рассказать о проекте на AngularAir, это отличные часы! Я расскажу о некоторых из тех же тем здесь, но немного подробнее.
Существует ряд УДИВИТЕЛЬНЫХ фреймворков для построения графиков, таких как HighCharts, Chart.js и кто мог бы забыть все лучшее из них D3.js! Проблема в том, что когда мы приступили к созданию пользовательской визуализации, их было сложно собрать воедино. Были и другие проблемы, они нарушили единую точку контактной политики DOM.
Чтобы создать сложный набор таких визуализаций многократного использования, вам нужно разбить каждую диаграмму до ее голой концепции. Итак, возьмите гистограмму, подобную этой:

В этой диаграмме у нас есть следующие компоненты:
- Бары
- Ось X
- Ось Y
- Легенда
- Линии сетки
- Этикетки
- Всплывающие подсказки при наведении
затем есть сама диаграмма, которая склеивает все это воедино. Это много чего! Большинство людей построят каждый из этих компонентов в одном огромном компоненте, но что произойдет, если вы захотите повторно использовать его для горизонтальной гистограммы? Или вы хотите повторно использовать линии сетки на линейном графике? Поскольку мы полностью разобрали его до самой сути, вы можете это сделать! Он создает действительно многоразовые диаграммы!
Мы предоставляем множество диаграмм сразу после установки, но невозможно охватить каждый случай. Давайте посмотрим, как будет выглядеть построение пользовательской гистограммы в ngx-charts:
<ngx-charts-chart
[view]="[width, height]"
[showLegend]="false">
<svg:g class="bar-chart chart">
<svg:g
ngx-charts-series-vertical
[xScale]="xScale"
[yScale]="yScale"
[colors]="colors"
[series]="results"
[dims]="dims">
</svg:g>
</svg:g>
</ngx-charts-chart>
В приведенном выше примере вы можете видеть, что мы оборачиваем компонент в ngx-charts-chart компонент. Это клей для всех дочерних компонентов SVG. Он включает в себя такие вещи, как легенды, расчет размеров и многое другое. Затем мы определяем группу svg: g, которая также содержит компонент атрибута с именем ngx-charts-series-vertical. Вы заметите, что здесь мы использовали svg:g элемент DOM вместо нашего собственного селектора компонентов. Это потому, что спецификация DOM очень строго относится к иерархии элементов SVG. В Angular1 мы могли бы использовать атрибут replace в директиве, но он пропал в Angular2, поэтому вместо этого мы будем использовать селектор атрибутов компонента.
Компонент вертикального ряда является «мясом» этого компонента, он содержит:
- Набор компонентов стержня
- Масштаб оси X
Код TypeScript в компоненте немного больше похож на то, что вы можете найти в компоненте D3 (в конце концов, мы используем его под капотом).
import { Component, Input, OnChanges } from '@angular/core';
import { BaseChartComponent, ColorHelper } from 'ngx-charts';
import * as d3 from 'd3';
@Component({
selector: 'custom-chart',
templateUrl: './custom.component.html',
styleUrls: ['./custom.component.css']
})
export class CustomChartComponent extends BaseChartComponent implements OnChanges {
dims: any;
xScale: any;
yScale: any;
xDomain: any;
yDomain: any;
colors: ColorHelper;
colorScheme: any = 'cool';
@Input() view;
@Input() results;
ngOnChanges() {
this.update();
}
update() {
super.update();
this.dims = {
width: this.width,
height: this.height
};
this.xScale = this.getXScale();
this.yScale = this.getYScale();
this.setColors();
}
getXScale() {
const spacing = 0.2;
this.xDomain = this.getXDomain();
return d3.scaleBand()
.rangeRound([0, this.dims.width])
.paddingInner(spacing)
.domain(this.xDomain);
}
getYScale() {
this.yDomain = this.getYDomain();
return d3.scaleLinear()
.range([this.dims.height, 0])
.domain(this.yDomain);
}
getXDomain() {
return this.results.map(d => d.name);
}
getYDomain() {
let values = this.results.map(d => d.value);
let min = Math.min(0, ...values);
let max = Math.max(...values);
return [min, max];
}
setColors() {
this.colors = new ColorHelper(this.colorScheme, 'ordinal', this.xDomain);
}
}
Вот и все, что касается полностью настраиваемой гистограммы. У вас есть доступ ко всем элементам SVG здесь, чтобы управлять ими, как вы хотите. Если вы хотите опуститься и испачкаться, вы даже можете свернуть компоненты своей собственной серии. Когда мы начинаем его реализовывать, он оказывается очень чистым и легко компонуемым компонентом в представлении нашего приложения:
import { Component } from '@angular/core';
@Component({
selector: 'app',
template: `
<div>
<h2>Custom Chart</h2>
<custom-chart
[view]="[600,300]"
[results]="data">
</custom-chart>
</div>
`
})
export class AppComponent {
colorScheme = {
domain: ['#F44336', '#3F51B5', '#8BC34A', '#2196F3', '#009688', '#FF5722', '#CDDC39', '#00BCD4', '#FFC107', '#795548', '#607D8B']
};
data = [
{
"name": "Germany",
"value": 46268
},
{
"name": "USA",
"value": 53041
},
{
"name": "France",
"value": 42503
},
{
"name": "United Kingdom",
"value": 41787
},
{
"name": "Spain",
"value": 29863
},
{
"name": "Italy",
"value": 35925
}
];
}
Есть так много интересных вещей, которые вы можете начать делать, когда начнете думать о том, как можно использовать Angular по-разному, помимо того мышления, к которому мы привыкли в Angular1. Если вам интересно увидеть работающий приведенный выше код, ознакомьтесь с этим репозиторием Github.

Надеюсь, вам понравился пост, если он вам понравился, подпишитесь на меня в Twitter и Github, чтобы получить больше советов / мнений / проектов / статей / и т. Д. По JavaScript!