angular-advance-chart
Version:
Angular Advance Chart provides chart solution for Angular.Currently supports Bar, Pie and Donut chart
448 lines (439 loc) • 18.3 kB
JavaScript
import { __decorate } from 'tslib';
import { CommonModule } from '@angular/common';
import { EventEmitter, Output, Input, Component, ViewChildren, ElementRef, Renderer2, HostListener, Directive, NgModule } from '@angular/core';
let BarChartComponent = class BarChartComponent {
constructor() {
this.selectedItem = new EventEmitter();
this.chartData = [];
this.chartOptions = {
roundedCorners: false,
isHorizontal: false,
showLegend: true,
legendTitle: 'Total',
};
this.view = {
height: 200,
width: 200
};
this.lines = [];
this.totalSum = 0;
this.isHorizontal = true;
this.barLineType = 'round';
this.chartView = [];
this.scale = 100;
}
ngOnInit() {
this.chartView.push(this.view.height + 'px');
this.chartView.push(this.view.width + 'px');
this.barLineType = this.chartOptions['roundedCorners'] ? 'round' : 'butt';
this.isHorizontal = this.chartOptions['isHorizontal'] ? true : false;
this.scale = this.isHorizontal ? this.view.width : this.view.height;
this.getTotalSum(this.chartData);
let value = Math.max.apply(Math, this.chartData.map(function (o) {
return o.value;
}));
if (value > this.scale) {
let normalizedValue = value / this.scale;
this.chartData.map((y, index) => {
this.chartData[index]['normalized'] = Number(y.value) / normalizedValue;
});
}
else {
let normalizedValue = this.scale / value;
this.chartData.map((y, index) => {
this.chartData[index]['normalized'] = Number(y.value) * normalizedValue;
});
}
this.lines = this.isHorizontal ? this.calculateHorizontalBarLines(this.chartData) : this.calculateVerticalBarLines(this.chartData);
}
ngAfterViewInit() { }
getItemClicked(line) {
let selectedbar = {
name: line.name,
value: line.value
};
this.selectedItem.emit(JSON.stringify(selectedbar));
}
calculateHorizontalBarLines(graphData) {
let barLines = [];
graphData.map((x, index) => {
let background = {
x1: 10,
y1: index * 20 + 20,
y2: index * 20 + 20,
x2: this.view.width,
color: '#EBEBEB',
name: x.name,
value: x.value
};
barLines.push(background);
if (x.value > 0) {
let line = {
x1: 10,
y1: index * 20 + 20,
y2: index * 20 + 20,
x2: x.normalized < 10 ? this.barLineType == 'butt' ? 11 : 10 : x.normalized,
color: x.color,
name: x.name,
value: x.value
};
barLines.push(line);
}
});
return barLines;
}
calculateVerticalBarLines(graphData) {
let barLines = [];
graphData.map((x, index) => {
let background = {
x1: index * 20 + 20,
y1: 10,
x2: index * 20 + 20,
y2: this.scale,
color: '#EBEBEB',
name: x.name,
value: x.value
};
barLines.push(background);
if (x.value > 0) {
let line = {
x1: index * 20 + 20,
y1: (this.scale + 10) - x.normalized > this.scale ? this.barLineType == 'butt' ? (this.scale - 1) : this.scale : (this.scale + 10) - x.normalized,
x2: index * 20 + 20,
y2: this.scale,
color: x.color,
name: x.name,
value: x.value
};
barLines.push(line);
}
});
console.log(barLines);
return barLines;
}
getTotalSum(chartData) {
// Get total number of records
this.totalSum = chartData.reduce(function (a, b) {
return a + parseInt(b.value);
}, 0);
}
};
__decorate([
Output()
], BarChartComponent.prototype, "selectedItem", void 0);
__decorate([
Input()
], BarChartComponent.prototype, "chartData", void 0);
__decorate([
Input()
], BarChartComponent.prototype, "chartOptions", void 0);
__decorate([
Input()
], BarChartComponent.prototype, "view", void 0);
BarChartComponent = __decorate([
Component({
selector: 'ngx-bar-chart',
template: "<div class=\"chart-view ngx-bar\">\n <div class=\"chart-wrapper\" [ngStyle]=\"{'height': chartView[0],'width': chartView[1]}\">\n <svg id=\"lines\" [attr.viewBox]=\"'0 0 '+ (isHorizontal ? scale+40 : (lines[lines.length-1].x1 + 20))+' ' + (isHorizontal ? (lines[lines.length-1].y2 + 20) : (scale+20))\">\n <g>\n <line *ngFor=\"let line of lines\" stroke-width=\"10\" class=\"line\" [attr.x1]=\"line.x1\" [attr.y1]=\"line.y1 \"\n [attr.x2]=\"line.x2\" [attr.y2]=\"line.y2\" [attr.stroke]=\"line.color\" \u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0 [attr.stroke-linecap]=\"barLineType\"\n [attr.title]=\"line.name\" (click)=\"getItemClicked(line)\" chartTooltip tooltip={{line.name}} />\n </g>\n </svg>\n </div>\n <div class=\"legend\" *ngIf=\"chartOptions.showLegend\">\n <h4>{{chartOptions.legendTitle +' : '+ totalSum}}</h4>\n <div class=\"legend-item\" *ngFor=\"let item of chartData; let i=index\">\n <div class=\"legend-item-colour\" [ngStyle]=\"{'background': item.color}\"></div><span\n class=\"legend-item-name\">{{item.name}}</span><span class=\"legend-item-value\">{{item.value}}</span>\n </div>\n </div>\n\n</div>",
styles: [".line{cursor:pointer}"]
})
], BarChartComponent);
let DonutChartComponent = class DonutChartComponent {
constructor() {
this.selectedItem = new EventEmitter();
this.chartOptions = {
showLegend: true,
legendTitle: 'Total',
};
this.view = {
height: 200,
width: 200,
radius: 80,
donutSize: 20
};
this.totalSum = 0;
this.processedData = [];
this.legendData = [];
this.chartView = [];
}
ngOnInit() {
if (this.chartData) {
this.view['donutSize'] = this.view['donutSize'] ? this.view['donutSize'] : 20;
this.chartView.push(this.view.height + 'px');
this.chartView.push(this.view.width + 'px');
// Get total number of records
this.totalSum = this.chartData.reduce(function (a, b) {
return a + b.value;
}, 0);
//generate Data for list
let prevAngle = 0;
this.chartData.map((x, index) => {
let legend = {
name: x.name,
value: x.value,
color: x.color
};
this.legendData.push(legend);
let percentage = this.getPercentage(x.value, this.totalSum);
if (percentage > 0) {
let circlePercentage = percentage / 10 * 36;
let pieData = {
color: x.color,
a1: prevAngle,
a2: prevAngle + circlePercentage,
name: x.name
};
prevAngle = prevAngle + circlePercentage;
this.processedData.push(pieData);
}
});
}
}
getPercentage(partialValue, totalValue) {
return (100 * partialValue) / totalValue;
}
ngAfterViewInit() {
//create svg
if (this.processedData.length > 0) {
this.span.map((item, index) => {
item.nativeElement.setAttribute('d', this.describeArc(this.view.height / 2, this.view.width / 2, this.view.radius, this.processedData[index].a1, this.processedData[index].a2 == 360 ? 359.99 : this.processedData[index].a2));
item.nativeElement.setAttribute('stroke', this.processedData[index].color);
});
}
}
polarToCartesian(centerX, centerY, radius, angleInDegrees) {
let angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
describeArc(x, y, radius, startAngle, endAngle) {
let start = this.polarToCartesian(x, y, radius, endAngle);
let end = this.polarToCartesian(x, y, radius, startAngle);
let largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
let d = [
"M", start.x, start.y,
"A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
].join(" ");
return d;
}
getItemClicked(item) {
let selected = {
name: item.name,
value: item.value
};
this.selectedItem.emit(selected);
}
show(status) {
}
};
__decorate([
Input()
], DonutChartComponent.prototype, "chartData", void 0);
__decorate([
Output()
], DonutChartComponent.prototype, "selectedItem", void 0);
__decorate([
ViewChildren('el')
], DonutChartComponent.prototype, "span", void 0);
__decorate([
Input()
], DonutChartComponent.prototype, "chartOptions", void 0);
__decorate([
Input()
], DonutChartComponent.prototype, "view", void 0);
DonutChartComponent = __decorate([
Component({
selector: 'ngx-donut-chart',
template: "<div class=\"chart-view ngx-donut\">\n <svg class=\"chart-wrapper\" [ngStyle]=\"{'height': chartView[0],'width': chartView[1]}\">\n <path width=\"100%\" height=\"100%\" #el fill=\"none\" [attr.stroke-width]=\"this.view.donutSize\" *ngFor=\"let item of processedData; let i=index\"\n (click)=\"getItemClicked(item)\" chartTooltip tooltip={{item.name}}/>\n\n </svg>\n <div class=\"legend\" *ngIf=\"chartOptions.showLegend\">\n <h4>{{chartOptions.legendTitle +' : '+ totalSum}}</h4>\n <div class=\"legend-item\" *ngFor=\"let item of legendData; let i=index\" >\n <div class=\"legend-item-colour\" [ngStyle]=\"{'background': item.color}\"></div><span class=\"legend-item-name\" >{{item.name}}</span><span class=\"legend-item-value\" >{{item.value}}</span>\n </div>\n </div>\n</div>",
styles: ["path:hover{cursor:pointer}"]
})
], DonutChartComponent);
let PieChartComponent = class PieChartComponent {
constructor() {
this.selectedItem = new EventEmitter();
this.chartOptions = {
showLegend: true,
legendTitle: 'Total',
};
this.view = {
height: 200,
width: 200,
radius: 80
};
this.chartView = [];
this.totalSum = 0;
this.processedData = [];
this.legendData = [];
}
ngOnInit() {
this.chartView.push(this.view.height + 'px');
this.chartView.push(this.view.width + 'px');
if (this.chartData) {
// Get total number of records
this.totalSum = this.chartData.reduce(function (a, b) {
return a + b.value;
}, 0);
//generate Data for piechart
let prevAngle = 0;
this.chartData.map((x, index) => {
let legend = {
name: x.name,
value: x.value,
color: x.color
};
this.legendData.push(legend);
let percentage = this.getPercentage(x.value, this.totalSum);
if (percentage > 0) {
let circlePercentage = percentage / 10 * 36;
let pieData = {
color: x.color,
a1: prevAngle,
a2: prevAngle + circlePercentage,
name: x.name
};
prevAngle = prevAngle + circlePercentage;
this.processedData.push(pieData);
}
});
}
}
ngAfterViewInit() {
// create svg
if (this.processedData.length > 0) {
this.span.map((item, index) => {
this.processedData[index].a2 = this.processedData[index].a2 >= 360 ? 359.9 : this.processedData[index].a2;
item.nativeElement.setAttribute('d', this.describeArc(this.view.height / 2, this.view.height / 2, this.view.radius, this.processedData[index].a1, this.processedData[index].a2));
item.nativeElement.setAttribute('fill', this.processedData[index].color);
});
}
}
polarToCartesian(centerX, centerY, radius, angleInDegrees) {
let angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
describeArc(x, y, radius, startAngle, endAngle) {
let start = this.polarToCartesian(x, y, radius, endAngle);
let end = this.polarToCartesian(x, y, radius, startAngle);
let arcSweep = endAngle - startAngle <= 180 ? "0" : "1";
let d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y,
"L", x, y,
"L", start.x, start.y
].join(" ");
return d;
}
getPercentage(partialValue, totalValue) {
return (100 * partialValue) / totalValue;
}
getItemClicked(item) {
let selected = {
name: item.name,
value: item.value
};
this.selectedItem.emit(selected);
}
};
__decorate([
Input()
], PieChartComponent.prototype, "chartData", void 0);
__decorate([
ViewChildren('el')
], PieChartComponent.prototype, "span", void 0);
__decorate([
Output()
], PieChartComponent.prototype, "selectedItem", void 0);
__decorate([
Input()
], PieChartComponent.prototype, "chartOptions", void 0);
__decorate([
Input()
], PieChartComponent.prototype, "view", void 0);
PieChartComponent = __decorate([
Component({
selector: 'ngx-pie-chart',
template: "<div class=\"chart-view ngx-pie\">\n <svg class=\"chart-wrapper\" [ngStyle]=\"{'height': chartView[0],'width': chartView[1]}\">\n <path #el class=\"pie-chart-path\" chartTooltip tooltip={{item.name}} (click)=\"getItemClicked(item)\" *ngFor=\"let item of processedData; let i=index\" />\n </svg>\n <div class=\"legend\" *ngIf=\"chartOptions.showLegend\">\n <h4>{{chartOptions.legendTitle +' : '+ totalSum}}</h4>\n <div class=\"legend-item\" *ngFor=\"let item of legendData; let i=index\">\n <div class=\"legend-item-colour\" [ngStyle]=\"{'background': item.color}\"></div><span class=\"legend-item-name\" >{{item.name}}</span><span class=\"legend-item-value\" >{{item.value}}</span>\n </div>\n </div>\n</div>",
styles: ["path.pie-chart-path:hover{cursor:pointer}"]
})
], PieChartComponent);
let TooltipDirective = class TooltipDirective {
constructor(el, renderer) {
this.el = el;
this.renderer = renderer;
}
onMouseEnter(event) {
if (!this.tooltip) {
this.show(event);
}
}
onMouseLeave() {
if (this.tooltip) {
this.hide();
}
}
show(event) {
this.create();
this.setPosition(event);
this.renderer.addClass(this.tooltip, 'chart-tooltip-show');
}
hide() {
this.renderer.removeClass(this.tooltip, 'chart-tooltip-show');
this.renderer.removeChild(document.body, this.tooltip);
this.tooltip = null;
}
create() {
this.tooltip = this.renderer.createElement('span');
this.renderer.appendChild(this.tooltip, this.renderer.createText(this.tooltipTitle) // textNode
);
this.renderer.appendChild(document.body, this.tooltip);
this.renderer.addClass(this.tooltip, 'chart-tooltip');
}
setPosition(event) {
const scrollPos = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
let top = event.y;
let left = event.x;
this.renderer.setStyle(this.tooltip, 'top', `${top + scrollPos}px`);
this.renderer.setStyle(this.tooltip, 'left', `${left}px`);
}
};
TooltipDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 }
];
__decorate([
Input('tooltip')
], TooltipDirective.prototype, "tooltipTitle", void 0);
__decorate([
HostListener('mouseenter', ['$event'])
], TooltipDirective.prototype, "onMouseEnter", null);
__decorate([
HostListener('mouseleave')
], TooltipDirective.prototype, "onMouseLeave", null);
TooltipDirective = __decorate([
Directive({
selector: '[chartTooltip]'
})
], TooltipDirective);
let AngularAdvanceChartModule = class AngularAdvanceChartModule {
};
AngularAdvanceChartModule = __decorate([
NgModule({
declarations: [PieChartComponent, BarChartComponent, DonutChartComponent, TooltipDirective],
imports: [
CommonModule
],
exports: [PieChartComponent, BarChartComponent, DonutChartComponent]
})
], AngularAdvanceChartModule);
/*
* Public API Surface of angular-advance-chart
*/
/**
* Generated bundle index. Do not edit.
*/
export { AngularAdvanceChartModule, BarChartComponent, DonutChartComponent, PieChartComponent, TooltipDirective as ɵa };
//# sourceMappingURL=angular-advance-chart.js.map