ng-d3-graphs
Version:
<img src="./assets/ng-d3.png" alt="drawing" width="250" height="250"/>
1,275 lines (1,253 loc) • 51.6 kB
JavaScript
import { __spread, __decorate, __assign, __param, __values } from 'tslib';
import { ɵɵdefineInjectable, Injectable, ElementRef, Input, HostListener, Component, ViewEncapsulation, NgModule, ChangeDetectionStrategy, Inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { axisLeft, axisBottom, axisRight, axisTop, line, scaleLinear, extent, scaleBand, timeFormat, select, timeParse, scaleTime, min, max, curveStep, area, utcParse, schemeSet2, scaleOrdinal, pie, entries, arc, interpolateCool } from 'd3';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
var axisConfig = {
color: 'lightgrey',
opacity: 1,
rendering: 'crispEdges',
strokeWidth: '1px',
xAxisTimeParser: '%Y-%m-%dT%H:%M:%S.%LZ',
xAxisTimeFormat: '%m/%d/%y',
xAxisTicks: 5,
};
var AxisDirection;
(function (AxisDirection) {
AxisDirection["top"] = "top";
AxisDirection["right"] = "right";
AxisDirection["bottom"] = "bottom";
AxisDirection["left"] = "left";
})(AxisDirection || (AxisDirection = {}));
var D3Service = /** @class */ (function () {
function D3Service() {
}
D3Service.prototype.translate = function (x, y) {
return "translate(" + x + ", " + y + ")";
};
D3Service.prototype.factoryAxis = function (scale, direction) {
switch (direction) {
case AxisDirection.top:
return axisTop(scale);
case AxisDirection.right:
return axisRight(scale);
case AxisDirection.bottom:
return axisBottom(scale);
case AxisDirection.left:
return axisLeft(scale);
default:
return new Error('No axis Direction Provided');
}
};
D3Service.prototype.factoryLine = function () {
return line().x(function (d) { return d.x; }).y(function (d) { return d.y; });
};
// ==== Axis =====
D3Service.prototype.scaleLinearX = function (labels, width) {
return scaleLinear()
.domain(extent(labels)) // does the magic for adjustable axis
.range([0, width]);
};
D3Service.prototype.scaleLinearY = function (data, height) {
return scaleLinear()
.domain(extent(data)) // does the magic for adjustable axis
.range([height, 0]);
};
D3Service.prototype.scaleBandX = function (labels, width) {
return scaleBand().domain(labels).rangeRound([0, width]).padding(0.1);
};
D3Service.prototype.scaleLinearYRangeRound = function (data, height) {
return scaleLinear().domain([0, Math.max.apply(Math, __spread(data))]).rangeRound([
height, 0
]);
};
D3Service.prototype.addLabelAxisY = function (svg, height, options) {
svg.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 0 - options.margin.left)
.attr('x', 0 - height / 2)
.attr('dy', '1em')
.style('text-anchor', 'middle')
.text(options.yAxisLabel);
};
D3Service.prototype.addLabelAxisX = function (svg, width, height, options) {
svg.append('text')
.attr('transform', 'translate(' + width / 2 + ' ,' + (height + options.margin.top) +
')')
.style('text-anchor', 'middle')
.text(options.xAxisLabel);
};
D3Service.prototype.getViewBoxDefault = function (options) {
var res = {
minX: -options.margin.left,
minY: -25,
width: options.width,
height: options.height - options.margin.top,
};
return res;
};
D3Service.prototype.removeAxisTicks = function (axis) {
axis.selectAll('.tick').selectAll('line').remove();
};
D3Service.prototype.changeAxisColor = function (axis, config) {
axis.select('path')
.attr('color', config.color)
.attr('opacity', config.opacity)
.attr('rendering', config.rendering)
.attr('stroke-width', config.strokeWidth);
};
D3Service.prototype.getXaxisTime = function (svg, height, x, timeFormat$1, xAxisTicks) {
return svg.append('g')
.attr('transform', "translate(0," + height + ")")
.call(axisBottom(x)
.tickFormat(timeFormat(timeFormat$1))
.ticks(xAxisTicks));
};
D3Service.prototype.hideTooltip = function (tooltipText, tooltip) {
tooltipText.selectAll('tspan').remove();
tooltip.attr('visibility', 'hidden');
};
D3Service.prototype.showTooltip = function (d, xScale, yScale, tooltip, tooltipRect, tooltipText, formatTime) {
var xPos = xScale(d.x) - 150 / 2;
var yPos = yScale(d.y) + 10;
tooltip.attr('transform', "translate(" + xPos + ", " + yPos + ")")
.attr('is', true)
.attr('visibility', 'visible');
tooltipRect.attr('opacity', 0.7);
tooltipText.attr('tranform', 'translate(75,30)')
.attr('fill', 'white')
.attr('font-size', 10)
.attr('font-family', "'Roboto', 'sans-serif'");
tooltipText.append('tspan')
.attr('text-anchor', 'middle')
.attr('is', true)
.attr('x', 25)
.attr('y', -5)
.text("" + formatTime(d.x));
tooltipText.append('tspan')
.attr('text-anchor', 'middle')
.attr('is', true)
.attr('x', 20)
.attr('dy', 15)
.text("" + d.y);
};
D3Service.prototype.addTooltip = function (container) {
var tooltipConfig = {
width: 100,
height: 40,
fill: '#333',
opacity: 0.7,
rx: 15,
text: {
translateX: 10,
translateY: 20,
},
};
var tooltip = select(container.nativeElement).select('svg').append('g');
var tooltipRect = tooltip.append('rect')
.attr('width', tooltipConfig.width)
.attr('height', tooltipConfig.height)
.attr('fill', tooltipConfig.fill)
.attr('opacity', 0)
.attr('rx', tooltipConfig.rx);
var tooltipText = tooltip.append('text').attr('transform', "translate(\n " + tooltipConfig.text.translateX + ",\n " + tooltipConfig.text.translateY + ")");
return { tooltip: tooltip, tooltipRect: tooltipRect, tooltipText: tooltipText, tooltipConfig: tooltipConfig };
};
D3Service.ngInjectableDef = ɵɵdefineInjectable({ factory: function D3Service_Factory() { return new D3Service(); }, token: D3Service, providedIn: "root" });
D3Service = __decorate([
Injectable({ providedIn: 'root' })
], D3Service);
return D3Service;
}());
var BandComponent = /** @class */ (function () {
function BandComponent(container, d3Service) {
this.container = container;
this.d3Service = d3Service;
this.data = [];
this.labels = [];
this.options = {};
this.labelsAndData = [];
this.viewBox = {};
this._options = {
width: 879,
height: 804,
margin: { top: 50, right: 50, bottom: 50, left: 50 },
yAxisLabel: '',
gridTicks: 0,
timeParser: axisConfig.xAxisTimeParser,
timeFormat: axisConfig.xAxisTimeFormat,
xAxisTicks: axisConfig.xAxisTicks,
};
this.parseTime = timeParse(this.options.timeParser);
this.formatTime = timeFormat(this.options.timeFormat);
this.onResize$ = new Subject();
}
BandComponent.prototype.onResize = function () {
this.onResize$.next();
};
BandComponent.prototype.ngOnInit = function () {
this.options = __assign({}, this._options, this.options);
this.viewBox = {
minX: -this.options.margin.left,
minY: -10,
width: this.options.width + this.options.margin.left +
this.options.margin.right,
height: this.options.height + this.options.margin.top,
};
this.parseTime = timeParse(this.options.timeParser);
this.formatTime = timeFormat(this.options.timeFormat);
this.labels = this.formatLabels();
this.labelsAndData = this.combineLabelsDataToOne();
this.onResizeEvent();
this.render();
};
BandComponent.prototype.formatLabels = function () {
var _this = this;
return this.labels.map(function (d) { return _this.parseTime(d); });
};
BandComponent.prototype.combineLabelsDataToOne = function () {
var N = this.labels.length;
var result = [];
for (var index = 0; index < N; index++) {
result.push({
x: this.labels[index],
low: this.data[index].low,
high: this.data[index].high,
});
}
return result;
};
BandComponent.prototype.render = function () {
var currentWidth = parseInt(select(this.container.nativeElement).select('div').style('width'), 10);
var currentHeight = parseInt(select(this.container.nativeElement).select('div').style('height'), 10);
var width = this.options.width - this.options.margin.left -
this.options.margin.right;
var height = this.options.height - this.options.margin.top -
this.options.margin.bottom;
this.viewBox = {
minX: -this.options.margin.left,
minY: -10,
width: this.options.width,
height: this.options.height - this.options.margin.top,
};
var svg = select(this.container.nativeElement)
.select('div')
.append('svg')
.attr('width', currentWidth)
.attr('height', currentHeight)
.attr('viewBox', this.viewBox.minX + " " + this.viewBox.minY + " " + this.viewBox.width + " " + this.viewBox.height)
.classed('svg-content', true)
.append('g');
var x = scaleTime()
.domain(extent(this.labels, function (d) { return new Date(d); }))
.range([0, width]);
var y = scaleLinear()
.domain([
min(this.data, function (d) { return d.low; }), max(this.data, function (d) { return d.high; })
])
.nice(this.options.gridTicks)
.range([height, 0]);
// add the X gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_x_gridlines(x).tickSize(height)
// .tickFormat('')
);
// add the Y gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_y_gridlines(y).tickSize(-width)
// .tickFormat('')
);
var xAxis = this.d3Service.getXaxisTime(svg, height, x, this.options.timeFormat, this.options.xAxisTicks);
var yAxis = function (g) {
return g.attr('transform', "translate(" + 0 + ",0)").call(axisLeft(y));
};
var curve = curveStep;
var area$1 = area()
.curve(curve)
.x(function (d) { return x(d.x); })
.y0(function (d) { return y(d.low); })
.y1(function (d) { return y(d.high); });
var _yAxis = svg.append('g').call(yAxis);
// this.d3Service.addLabelAxisX(svg, width, height, this.options);
// text label for the x axis
this.addLabelAxisX(svg, width, height);
// text label for the y axis
this.addLabelAxisY(svg, height);
svg.append('path')
.datum(this.labelsAndData)
.attr('fill', 'steelblue')
.attr('d', area$1);
this.removeAxisTicks(xAxis);
this.removeAxisTicks(_yAxis);
this.changeAxisColor(xAxis, axisConfig);
this.changeAxisColor(_yAxis, axisConfig);
};
BandComponent.prototype.changeAxisColor = function (axis, config) {
this.d3Service.changeAxisColor(axis, config);
};
BandComponent.prototype.removeAxisTicks = function (axis) {
this.d3Service.removeAxisTicks(axis);
};
BandComponent.prototype.addLabelAxisY = function (svg, height) {
svg.append('text')
.attr('transform', 'rotate(0)')
.attr('y', 0 - this.options.margin.top / 2)
.attr('x', 0)
.attr('dy', '1em')
.style('text-anchor', 'start')
.text(this.options.yAxisLabel);
};
BandComponent.prototype.addLabelAxisX = function (svg, width, height) {
svg.append('text')
.attr('transform', 'translate(' + width / 2 + ' ,' +
(height + this.options.margin.top - 15) + ')')
.style('text-anchor', 'middle')
.text(this.options.xAxisLabel);
};
// gridlines in x axis function
BandComponent.prototype.make_x_gridlines = function (x) {
return axisBottom(x).ticks(this.options.gridTicks);
};
// gridlines in y axis function
BandComponent.prototype.make_y_gridlines = function (y) {
return axisLeft(y).ticks(this.options.gridTicks);
};
BandComponent.prototype.onResizeEvent = function () {
var _this = this;
this.onResize$.pipe(debounceTime(200)).subscribe(function () {
var svgExist = select(_this.container.nativeElement).select('svg');
if (svgExist) {
svgExist.remove();
}
_this.render();
});
};
BandComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: D3Service }
]; };
__decorate([
Input()
], BandComponent.prototype, "data", void 0);
__decorate([
Input()
], BandComponent.prototype, "labels", void 0);
__decorate([
Input()
], BandComponent.prototype, "options", void 0);
__decorate([
HostListener('window:resize')
], BandComponent.prototype, "onResize", null);
BandComponent = __decorate([
Component({
selector: 'ng-band',
template: "<div class=\"svg-container\"></div>\n",
encapsulation: ViewEncapsulation.None,
styles: [".svg-container{display:inline-block;position:relative;width:100%;height:100%;padding-bottom:100%;vertical-align:top;overflow:hidden}.svg-content{display:inline-block;position:absolute;top:0;left:0}.grid line{stroke:#d3d3d3;stroke-opacity:.4;shape-rendering:crispEdges}.grid path{stroke-width:0}.grid text{display:none}.area{fill:#4682b4}"]
})
], BandComponent);
return BandComponent;
}());
var BandModule = /** @class */ (function () {
function BandModule() {
}
BandModule = __decorate([
NgModule({
declarations: [BandComponent],
imports: [
CommonModule
],
exports: [BandComponent],
})
], BandModule);
return BandModule;
}());
var BarComponent = /** @class */ (function () {
function BarComponent(container, d3Service) {
this.container = container;
this.d3Service = d3Service;
this.data = [];
this.labels = [];
this.options = {};
this.graph = {
xAxis: [],
yAxis: [],
xAxisPath: '',
yAxisPath: '',
rectanglesData: [],
};
this.labelsAndData = [];
this.parseTime = timeParse('%d-%b-%y');
this._options = {
width: 879,
height: 804,
margin: { top: 50, right: 50, bottom: 50, left: 50 },
gridTicks: 0,
};
this.viewBox = {};
this.onResize$ = new Subject();
}
BarComponent.prototype.onResize = function () {
this.onResize$.next();
};
BarComponent.prototype.ngOnInit = function () {
this.options = __assign({}, this._options, this.options);
this.viewBox = {
minX: -this.options.margin.left,
minY: -10,
width: this.options.width + this.options.margin.left +
this.options.margin.right,
height: this.options.height + this.options.margin.top,
};
this.labelsAndData = this.combineLabelsDataToOne();
this.onResizeEvent();
this.render();
};
BarComponent.prototype.render = function () {
var currentWidth = parseInt(select(this.container.nativeElement).select('div').style('width'), 10);
var currentHeight = parseInt(select(this.container.nativeElement).select('div').style('height'), 10);
var width = this.options.width - this.options.margin.left -
this.options.margin.right;
var height = this.options.height - this.options.margin.top -
this.options.margin.bottom;
this.viewBox = {
minX: -this.options.margin.left,
minY: -10,
width: this.options.width,
height: this.options.height - this.options.margin.top,
};
var svg = select(this.container.nativeElement)
.select('div')
.append('svg')
.attr('width', currentWidth)
.attr('height', currentHeight)
.attr('viewBox', this.viewBox.minX + " " + this.viewBox.minY + " " + this.viewBox.width + " " + this.viewBox.height)
.classed('svg-content', true)
.append('g');
var x = scaleBand().rangeRound([0, width]).padding(0.1).domain(this.labels);
var y = scaleLinear().rangeRound([height, 0]).domain([
0,
Math.max.apply(Math, __spread(this.data.map(function (d) { return Number(d); })))
]);
var xAxis = function (g) { return g.call(axisBottom(x))
.attr('transform', 'translate(0,' + height + ')'); };
var yAxis = function (g) { return g.call(axisLeft(y)); };
// add the X gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_x_gridlines(x).tickSize(height)
// .tickFormat('')
);
// add the Y gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_y_gridlines(y).tickSize(-width)
// .tickFormat('')
);
svg.selectAll('.bar')
.data(this.labelsAndData)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', function (d) {
return x(d.x);
})
.attr('y', function (d) {
return y(Number(d.y));
})
.attr('width', x.bandwidth())
.attr('height', function (d) {
return height - y(Number(d.y));
});
var _xAxis = svg.append('g').call(xAxis);
// text label for the x axis
this.addLabelAxisX(svg, width, height);
var _yAxis = svg.append('g').call(yAxis);
// text label for the y axis
this.addLabelAxisY(svg, height);
this.removeAxisTicks(_xAxis);
this.removeAxisTicks(_yAxis);
this.changeAxisColor(_xAxis, axisConfig);
this.changeAxisColor(_yAxis, axisConfig);
};
BarComponent.prototype.changeAxisColor = function (axis, config) {
this.d3Service.changeAxisColor(axis, config);
};
BarComponent.prototype.removeAxisTicks = function (axis) {
this.d3Service.removeAxisTicks(axis);
};
BarComponent.prototype.addLabelAxisY = function (svg, height) {
svg.append('text')
.attr('transform', 'rotate(0)')
.attr('y', 0 - this.options.margin.top / 2)
.attr('x', 0)
.attr('dy', '1em')
.style('text-anchor', 'start')
.text(this.options.yAxisLabel);
};
BarComponent.prototype.addLabelAxisX = function (svg, width, height) {
svg.append('text')
.attr('transform', 'translate(' + width / 2 + ' ,' +
(height + this.options.margin.top - 15) + ')')
.style('text-anchor', 'middle')
.text(this.options.xAxisLabel);
};
BarComponent.prototype.combineLabelsDataToOne = function () {
var result = [];
var N = this.data.length;
for (var index = 0; index < N; index++) {
result.push({ x: this.labels[index], y: this.data[index] });
}
return result;
};
// gridlines in x axis function
BarComponent.prototype.make_x_gridlines = function (x) {
return axisBottom(x).ticks(this.options.gridTicks);
};
// gridlines in y axis function
BarComponent.prototype.make_y_gridlines = function (y) {
return axisLeft(y).ticks(this.options.gridTicks);
};
BarComponent.prototype.onResizeEvent = function () {
var _this = this;
this.onResize$.pipe(debounceTime(200)).subscribe(function () {
var svgExist = select(_this.container.nativeElement).select('svg');
if (svgExist) {
svgExist.remove();
}
_this.render();
});
};
BarComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: D3Service }
]; };
__decorate([
Input()
], BarComponent.prototype, "data", void 0);
__decorate([
Input()
], BarComponent.prototype, "labels", void 0);
__decorate([
Input()
], BarComponent.prototype, "options", void 0);
__decorate([
HostListener('window:resize')
], BarComponent.prototype, "onResize", null);
BarComponent = __decorate([
Component({
selector: 'ng-bar',
template: "\n<div class=\"svg-container\"></div>\n",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [".svg-container{display:inline-block;position:relative;width:100%;height:100%;padding-bottom:100%;vertical-align:top;overflow:hidden}.svg-content{display:inline-block;position:absolute;top:0;left:0}.grid line{stroke:#d3d3d3;stroke-opacity:.4;shape-rendering:crispEdges}.grid path{stroke-width:0}.grid text{display:none}.bar{fill:#4682b4}.bar:hover{fill:brown}"]
})
], BarComponent);
return BarComponent;
}());
var BarService = /** @class */ (function () {
function BarService() {
}
BarService = __decorate([
Injectable()
], BarService);
return BarService;
}());
var BarModule = /** @class */ (function () {
function BarModule() {
}
BarModule = __decorate([
NgModule({
declarations: [BarComponent],
imports: [
CommonModule
],
providers: [
BarService
],
exports: [BarComponent]
})
], BarModule);
return BarModule;
}());
var LineComponent = /** @class */ (function () {
function LineComponent(container, d3Service) {
this.container = container;
this.d3Service = d3Service;
this.data = [];
this.labels = [];
this.options = {};
this._options = {
width: 879,
height: 804,
margin: { top: 50, right: 50, bottom: 50, left: 50 },
gridTicks: 0,
yAxisLabel: '',
xAxisLabel: '',
timeParser: axisConfig.xAxisTimeParser,
timeFormat: axisConfig.xAxisTimeFormat,
xAxisTicks: axisConfig.xAxisTicks,
};
this.parseTime = timeParse(this.options.timeParser);
this.formatTime = timeFormat(this.options.timeFormat);
this.viewBox = {};
this.labelsAndData = [];
this.AxisDataX = [];
this.onResize$ = new Subject();
}
LineComponent.prototype.onResize = function () {
this.onResize$.next();
};
LineComponent.prototype.ngOnInit = function () {
var _this = this;
this.options = __assign({}, this._options, this.options);
this.viewBox = this.d3Service.getViewBoxDefault(this.options);
this.parseTime = timeParse(this.options.timeParser);
this.formatTime = timeFormat(this.options.timeFormat);
this.labels = this.labels.map(function (d) { return _this.parseTime(d); });
this.labelsAndData = this.combineLabelsDataToOne();
this.onResizeEvent();
this.render();
};
LineComponent.prototype.render = function () {
var currentWidth = parseInt(select(this.container.nativeElement).select('div').style('width'), 10);
var currentHeight = parseInt(select(this.container.nativeElement).select('div').style('height'), 10);
var width = this.options.width - this.options.margin.left -
this.options.margin.right;
var height = this.options.height - this.options.margin.top -
this.options.margin.bottom;
this.viewBox = {
minX: -this.options.margin.left,
minY: -10,
width: this.options.width,
height: this.options.height - this.options.margin.top,
};
var svg = select(this.container.nativeElement)
.select('div')
.append('svg')
.attr('width', currentWidth)
.attr('height', currentHeight)
.attr('viewBox', this.viewBox.minX + " " + this.viewBox.minY + " " + this.viewBox.width + " " + this.viewBox.height)
.classed('svg-content', true)
.append('g');
var x = scaleTime().range([0, width]);
var y = scaleLinear().range([height, 0]).nice();
var valueline = line().x(function (d) { return x(d.x); }).y(function (d) { return y(d.y); });
x.domain(extent(this.labels, function (d) { return (d); }));
y.domain([0, max(this.data, function (d) { return d; })]);
// add the X gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_x_gridlines(x).tickSize(height)
// .tickFormat('')
);
// add the Y gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_y_gridlines(y).tickSize(-width)
// .tickFormat('')
);
svg.append('path')
.datum(this.labelsAndData)
.attr('class', 'line')
.attr('d', valueline);
// add the X Axis
var xAxis = this.d3Service.getXaxisTime(svg, height, x, this.options.timeFormat, this.options.xAxisTicks);
// text label for the x axis
this.addLabelAxisX(svg, width, height);
// add the Y Axis
var yAxis = svg.append('g').call(axisLeft(y));
// text label for the y axis
this.addLabelAxisY(svg, height);
this.removeAxisTicks(xAxis);
this.removeAxisTicks(yAxis);
this.changeAxisColor(xAxis, axisConfig);
this.changeAxisColor(yAxis, axisConfig);
this.addDots(svg, x, y);
};
LineComponent.prototype.addDots = function (svg, x, y) {
var _this = this;
var dotRadius = 3;
var dotColor = '#4682b4';
// add tootlip
var _a = this.d3Service.addTooltip(this.container), tooltip = _a.tooltip, tooltipRect = _a.tooltipRect, tooltipText = _a.tooltipText, tooltipConfig = _a.tooltipConfig;
svg.selectAll('dot')
.data(this.labelsAndData)
.enter()
.append('circle')
.attr('r', dotRadius)
.attr('fill', dotColor)
.attr('cx', function (d) {
return x(d.x);
})
.attr('cy', function (d) {
return y(d.y);
})
.on('mouseover', function (d) {
_this.onMouseOver(d, x, y, tooltip, tooltipRect, tooltipText);
})
.on('mouseout', function (d) {
_this.onMouseOut(d, tooltip, tooltipText, tooltipConfig);
});
};
LineComponent.prototype.onMouseOver = function (d, xScale, yScale, tooltip, tooltipRect, tooltipText) {
// show tooltip
if (tooltip) {
this.d3Service.showTooltip(d, xScale, yScale, tooltip, tooltipRect, tooltipText, this.formatTime);
}
};
LineComponent.prototype.onMouseOut = function (d, tooltip, tooltipText, tooltipConfig) {
// hide tooltip
if (tooltip) {
this.d3Service.hideTooltip(tooltipText, tooltip);
}
};
LineComponent.prototype.changeAxisColor = function (axis, config) {
this.d3Service.changeAxisColor(axis, config);
};
LineComponent.prototype.removeAxisTicks = function (axis) {
this.d3Service.removeAxisTicks(axis);
};
LineComponent.prototype.addLabelAxisY = function (svg, height) {
svg.append('text')
.attr('transform', 'rotate(0)')
.attr('y', 0 - this.options.margin.top / 2)
.attr('x', 0)
.attr('dy', '1em')
.style('text-anchor', 'start')
.text(this.options.yAxisLabel);
};
LineComponent.prototype.addLabelAxisX = function (svg, width, height) {
svg.append('text')
.attr('transform', 'translate(' + width / 2 + ' ,' +
(height + this.options.margin.top - 15) + ')')
.style('text-anchor', 'middle')
.text(this.options.xAxisLabel);
};
LineComponent.prototype.combineLabelsDataToOne = function () {
var result = [];
var N = this.data.length;
for (var index = 0; index < N; index++) {
result.push({ x: this.labels[index], y: this.data[index] });
}
return result;
};
// gridlines in x axis function
LineComponent.prototype.make_x_gridlines = function (x) {
return axisBottom(x).ticks(this.options.gridTicks);
};
// gridlines in y axis function
LineComponent.prototype.make_y_gridlines = function (y) {
return axisLeft(y).ticks(this.options.gridTicks);
};
LineComponent.prototype.onResizeEvent = function () {
var _this = this;
this.onResize$.pipe(debounceTime(200)).subscribe(function () {
var svgExist = select(_this.container.nativeElement).select('svg');
if (svgExist) {
svgExist.remove();
}
_this.render();
});
};
LineComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: D3Service }
]; };
__decorate([
Input()
], LineComponent.prototype, "data", void 0);
__decorate([
Input()
], LineComponent.prototype, "labels", void 0);
__decorate([
Input()
], LineComponent.prototype, "options", void 0);
__decorate([
HostListener('window:resize')
], LineComponent.prototype, "onResize", null);
LineComponent = __decorate([
Component({
selector: 'ng-line',
template: "<div class=\"svg-container\"></div>\n",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [".svg-container{display:inline-block;position:relative;width:100%;height:100%;padding-bottom:100%;vertical-align:top;overflow:hidden}.svg-content{display:inline-block;position:absolute;top:0;left:0}.grid line{stroke:#d3d3d3;stroke-opacity:.4;shape-rendering:crispEdges}.grid path{stroke-width:0}.grid text{display:none}.line{fill:none;stroke:#4682b4;stroke-width:2px}div.tooltip{position:absolute;text-align:center;min-width:60px;min-height:28px;padding:5px;font:12px sans-serif;background:#b0c4de;border:0;border-radius:5px;pointer-events:none;color:#000}"]
})
], LineComponent);
return LineComponent;
}());
var LineService = /** @class */ (function () {
function LineService(config) {
this.config = config;
}
LineService.prototype.showConfig = function () {
console.log(this.config);
};
LineService.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: Inject, args: ['config',] }] }
]; };
LineService = __decorate([
Injectable(),
__param(0, Inject('config'))
], LineService);
return LineService;
}());
var LineModule = /** @class */ (function () {
function LineModule() {
}
LineModule_1 = LineModule;
LineModule.forRoot = function (config) {
return {
ngModule: LineModule_1,
providers: [
LineService,
{ provide: 'config', useValue: config },
]
};
};
var LineModule_1;
LineModule = LineModule_1 = __decorate([
NgModule({
declarations: [LineComponent,],
imports: [
CommonModule
],
exports: [LineComponent],
providers: [
LineService
]
})
], LineModule);
return LineModule;
}());
var MultilineComponent = /** @class */ (function () {
function MultilineComponent(container, d3Service) {
this.container = container;
this.d3Service = d3Service;
this.data = [];
this.labels = [];
this.options = {};
this.labelsAndData = [];
this.utcParse = utcParse('%Y-%m');
this.viewBox = {};
this._options = {
width: 879,
height: 804,
yAxisLabel: '',
xAxisLabel: '',
margin: { top: 50, right: 50, bottom: 50, left: 50 },
timeParser: axisConfig.xAxisTimeParser,
timeFormat: axisConfig.xAxisTimeFormat,
xAxisTicks: axisConfig.xAxisTicks,
};
this.parseTime = timeParse(this.options.timeParser);
this.formatTime = timeFormat(this.options.timeFormat);
this.onResize$ = new Subject();
}
MultilineComponent.prototype.onResize = function () {
this.onResize$.next();
};
MultilineComponent.prototype.ngOnInit = function () {
this.options = __assign({}, this._options, this.options);
this.viewBox = {
minX: -this.options.margin.left,
minY: -25,
width: this.options.width + this.options.margin.left +
this.options.margin.right,
height: this.options.height + this.options.margin.top,
};
this.parseTime = timeParse(this.options.timeParser);
this.formatTime = timeFormat(this.options.timeFormat);
this.labels = this.formatData();
this.labelsAndData = this.combineLabelsDataToOne();
this.onResizeEvent();
this.render();
};
MultilineComponent.prototype.formatData = function () {
var _this = this;
return this.labels.map(function (d) { return _this.parseTime(d); });
};
MultilineComponent.prototype.combineLabelsDataToOne = function () {
var result = [];
var N = this.data.length;
for (var index = 0; index < N; index++) {
result.push({ x: this.labels, y: this.data[index] });
}
return result;
};
MultilineComponent.prototype.render = function () {
var _this = this;
var currentWidth = parseInt(select(this.container.nativeElement).select('div').style('width'), 10);
var currentHeight = parseInt(select(this.container.nativeElement).select('div').style('height'), 10);
var width = this.options.width - this.options.margin.left -
this.options.margin.right;
var height = this.options.height - this.options.margin.top -
this.options.margin.bottom;
this.viewBox = {
minX: -this.options.margin.left,
minY: -10,
width: this.options.width,
height: this.options.height - this.options.margin.top,
};
var svg = select(this.container.nativeElement)
.select('div')
.append('svg')
.attr('width', currentWidth)
.attr('height', currentHeight)
.attr('viewBox', this.viewBox.minX + " " + this.viewBox.minY + " " + this.viewBox.width + " " + this.viewBox.height)
.classed('svg-content', true)
.append('g');
var xDomain = this.getXdomain();
var x = scaleTime().domain(xDomain).range([0, width]);
var y = scaleLinear()
.domain([0, max(this.data, function (d) { return max(d.values); })])
.range([height, 0])
.nice();
// const xAxis = (g) =>
// g.attr('transform', `translate(0,${height})`).call(d3.axisBottom(x));
var xAxis = this.d3Service.getXaxisTime(svg, height, x, this.options.timeFormat, this.options.xAxisTicks);
var yAxis = function (g) { return g.call(axisLeft(y)); };
var line$1 = line()
.defined(function (d) { return !isNaN(d); })
.x(function (d, i) { return x(_this.labels[i]); })
.y(function (d) { return y(d); });
// add the X gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_x_gridlines(x).tickSize(height)
// .tickFormat('')
);
// add the Y gridlines
svg.append('g')
.attr('class', 'grid')
.call(this.make_y_gridlines(y).tickSize(-width)
// .tickFormat('')
);
var _yAxis = svg.append('g').call(yAxis);
// text label for the x axis
this.addLabelAxisX(svg, width, height);
// text label for the y axis
this.addLabelAxisY(svg, height);
var path = svg.append('g')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 1.5)
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.selectAll('path')
.data(this.data)
.join('path')
.style('mix-blend-mode', 'multiply')
.attr('d', function (d) { return line$1(d.values); })
.text('this is ');
this.removeAxisTicks(xAxis);
this.removeAxisTicks(_yAxis);
this.changeAxisColor(xAxis, axisConfig);
this.changeAxisColor(_yAxis, axisConfig);
// TODO: comment in when issue #61 is fixed
/* svg.call(hover, path, this);
function hover(svg, path, _this) {
if ('ontouchstart' in document) {
svg.style('-webkit-tap-highlight-color', 'transparent')
.on('touchmove', moved)
.on('touchstart', entered)
.on('touchend', left);
} else {
svg.on('mousemove', moved)
.on('mouseenter', entered)
.on('mouseleave', left);
}
const dot = svg.append('g').attr('display', 'none');
dot.append('circle').attr('r', 2.5);
dot.append('text')
.attr('font-family', 'sans-serif')
.attr('font-size', 10)
.attr('text-anchor', 'middle')
.attr('y', -8);
function moved() {
d3.event.preventDefault();
const ym = y.invert(d3.event.layerY) as any;
const xm = x.invert(d3.event.layerX) as any;
const i1 = d3.bisectLeft(_this.labels, xm, 1);
const i0 = i1 - 1;
const i = xm - _this.labels[i0] > _this.labels[i1] - xm ? i1 : i0;
// const s = d3.least(_this.data, d => Math.abs(d.values[i] - ym));
const s = _this.least(_this.data, d => Math.abs(d.values[i] - ym), i,
ym); path.attr('stroke', d => d === s ? null : '#ddd') .filter(d => d === s)
.raise();
dot.attr(
'transform', `translate(${x(_this.labels[i])},${y(s.values[i])})`);
dot.select('text').text(s.name);
}
function entered() {
path.style('mix-blend-mode', null).attr('stroke', '#ddd');
dot.attr('display', null);
}
function left() {
path.style('mix-blend-mode', 'multiply').attr('stroke', null);
dot.attr('display', 'none');
}
}
*/
};
MultilineComponent.prototype.changeAxisColor = function (axis, config) {
this.d3Service.changeAxisColor(axis, config);
};
MultilineComponent.prototype.removeAxisTicks = function (axis) {
this.d3Service.removeAxisTicks(axis);
};
MultilineComponent.prototype.addLabelAxisY = function (svg, height) {
svg.append('text')
.attr('transform', 'rotate(0)')
.attr('y', 0 - this.options.margin.top / 2)
.attr('x', 0)
.attr('dy', '1em')
.style('text-anchor', 'start')
.text(this.options.yAxisLabel);
};
MultilineComponent.prototype.addLabelAxisX = function (svg, width, height) {
svg.append('text')
.attr('transform', 'translate(' + width / 2 + ' ,' +
(height + this.options.margin.top - 15) + ')')
.style('text-anchor', 'middle')
.text(this.options.xAxisLabel);
};
MultilineComponent.prototype.getXdomain = function () {
var domainExtent = extent(this.labels, function (d) { return d; });
return domainExtent.map(function (d) { return new Date(d); });
};
MultilineComponent.prototype.least = function (arr, filterFun, pos, ym) {
var tempValues = arr.map(function (d) { return filterFun(d); });
var minNum = Math.min.apply(Math, __spread(tempValues));
var graphHovered;
var minimax = tempValues[0];
var minPos = 0;
for (var i = 1; i < tempValues.length; i++) {
var element = tempValues[i];
if (element >= minimax) {
minPos = i;
minimax = element;
}
}
graphHovered = arr[minPos];
return graphHovered;
};
// gridlines in x axis function
MultilineComponent.prototype.make_x_gridlines = function (x) {
return axisBottom(x).ticks(this.options.gridTicks);
};
// gridlines in y axis function
MultilineComponent.prototype.make_y_gridlines = function (y) {
return axisLeft(y).ticks(this.options.gridTicks);
};
MultilineComponent.prototype.onResizeEvent = function () {
var _this = this;
this.onResize$.pipe(debounceTime(200)).subscribe(function () {
var svgExist = select(_this.container.nativeElement).select('svg');
if (svgExist) {
svgExist.remove();
}
_this.render();
});
};
MultilineComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: D3Service }
]; };
__decorate([
Input()
], MultilineComponent.prototype, "data", void 0);
__decorate([
Input()
], MultilineComponent.prototype, "labels", void 0);
__decorate([
Input()
], MultilineComponent.prototype, "options", void 0);
__decorate([
HostListener('window:resize')
], MultilineComponent.prototype, "onResize", null);
MultilineComponent = __decorate([
Component({
selector: 'ng-multiline',
template: "<div class=\"svg-container\"></div>\n",
encapsulation: ViewEncapsulation.None,
styles: [".svg-container{display:inline-block;position:relative;width:100%;height:100%;padding-bottom:100%;vertical-align:top;overflow:hidden}.svg-content{display:inline-block;position:absolute;top:0;left:0}.grid line{stroke:#d3d3d3;stroke-opacity:.4;shape-rendering:crispEdges}.grid path{stroke-width:0}.grid text{display:none}"]
})
], MultilineComponent);
return MultilineComponent;
}());
var MultilineModule = /** @class */ (function () {
function MultilineModule() {
}
MultilineModule = __decorate([
NgModule({
declarations: [MultilineComponent],
imports: [
CommonModule,
],
exports: [MultilineComponent],
})
], MultilineModule);
return MultilineModule;
}());
var PieComponent = /** @class */ (function () {
function PieComponent(container) {
this.container = container;
this.labels = [];
this.data = [];
this.backgroundColors = schemeSet2;
this.radius = 100;
this.options = {};
this.color = this.interpolateColor(); // range [0,1] -> builtin range of colors.
this.defaultSliceColor = 'steerblue';
this.labelsAndData = [];
this.viewBox = {};
this._options = {
width: 300,
height: 300,
margin: { top: 50, right: 50, bottom: 50, left: 50 },
};
this.onResize$ = new Subject();
}
PieComponent.prototype.onResize = function () {
this.onResize$.next();
};
PieComponent.prototype.ngOnInit = function () {
this.options = __assign({}, this._options, this.options);
this.viewBox = {
minX: -this.options.margin.left,
minY: 0,
width: Number(this.options.width) + Number(this.options.margin.left) + Number(this.options.margin.right),
height: this.options.height,
};
this.onBgdColorUndefined();
this.onResizeEvent();
this.render();
};
PieComponent.prototype.onBgdColorUndefined = function () {
var e_1, _a;
if (this.backgroundColors.length === 0) {
try {
// TODO: check linter
// for (let index = 0; index < this.data.length; index++) {
// this.backgroundColors.push(this.defaultSliceColor);
// }
for (var _b = __values(this.data), _c = _b.next(); !_c.done; _c = _b.next()) {
var iterator = _c.value;
this.backgroundColors.push(this.defaultSliceColor);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
}
};
PieComponent.prototype.render = function () {
var _this = this;
var currentWidth = parseInt(select(this.container.nativeElement).select('div').style('width'), 10);
var currentHeight = parseInt(select(this.container.nativeElement).select('div').style('height'), 10);
var radius = Math.min(this.options.width, this.options.height) / 2 - this.options.margin.top;
var svg = select(this.container.nativeElement)
.select('div')
.append('svg')
.attr('width', currentWidth)
.attr('height', currentHeight)
.attr('viewBox', this.viewBox.minX + " " + this.viewBox.minY + " " + this.viewBox.width + " " + this.viewBox.height)
.classed('svg-content', true)
.append('g')
.attr('transform', 'translate(' + this.options.width / 2 + ',' + this.options.height / 2 + ')');
var color = scaleOrdinal().domain(this.data).range(this.backgroundColors);
var pie$1 = pie().value(function (d) { return d.value; });
var pieData = pie$1(entries(this.data));
var arcGenerator = arc().innerRadius(0).outerRadius(radius);
svg
.selectAll('slices')
.data(pieData)
.enter()
.append('path')
.attr('d', arcGenerator)
.attr('fill', function (d) { return _this.backgroundColors[d.index]; })
.attr('stroke', 'black')
.style('stroke-width', '2px')
.style('opacity', 0.7);
svg
.selectAll('slices')
.data(pieData)
.enter()
.append('text')
.text(function (d) { return _this.labels[d.index]; })
.attr('transform', function (d) {
return ('translate(' +
arcGenerator.centroid({
startAngle: d.startAngle,
endAngle: d.endAngle,
}) +
')');
})
.style('text-anchor', 'middle')
.style('font-size', 17);
this.addLabelAxisX(svg, this.options.width, this.options.height);
};
PieComponent.prototype.addLabelAxisX = function (svg, width, height) {
svg
.append('text')
.attr('transform', "translate(" + 0 + ", " + this.options.margin.top * 2.5 + ")")
.style('text-anchor', 'middle')
.text(this.options.xAxisLabel);
};
/**
* range [0, 1]
*/
PieComponent.prototype.interpolateColor = function () {
return interpolateCool;
};
PieComponent.prototype.combineLabelsDataToOne = function () {
var result = [];
var N = this.data.length;
for (var index = 0; index < N; index++) {
result.push({ x: this.labels[index], y: this.data[index] });
}
return result;
};
PieComponent.prototype.onResizeEvent = function () {
var _this = this;
this.onResize$.pipe(debounceTime(200)).subscribe(function () {
var svgExist = select(_this.container.nativeElement).select('svg');
if (svgExist) {
svgExist.remove();
}
_this.render();
});
};
PieComponent.ctorParameters = function () { return [
{ type: ElementRef }
]; };
__decorate([
Input()
], PieComponent.prototype, "labels", void 0);
__decorate([
Input()
], PieComponent.prototype, "data", void 0);
__decorate([
Input()
], PieComponent.prototype, "backgroundColors", void 0);
__decorate([
Input()
], PieComponent.prototype, "radius", void 0);
__decorate([
Input()
], PieComponent.prototype, "options", void 0);
__decorate([
HostListener('window:resize')
], PieComponent.prototype, "onResize", null);
PieComponent = __decorate([
Component({
selector: 'ng-pie',