lencse-getmdl-dashboard
Version:
Free dashboard template with Material Design Lite edited by @lencse
268 lines (236 loc) • 8.32 kB
JavaScript
{
class LineChart {
constructor(columns, color, margin, data, nv) {
this.columns = columns;
this.color = color;
this.margin = margin;
this.data = data;
this.nv = nv;
this.maxX = 130;
this.drawStep = 6; // It shows how many points will be drawn in one step
this.durationResizeAnimation = 500;
}
_addSvgContainer() {
this.svg = d3.select('.line-chart__container')
.append('div')
.append('svg');
}
_getSvgSizes() {
let svgWidth = getComputedStyle(this.svg[0][0]).width,
svgHeight = getComputedStyle(this.svg[0][0]).height;
this.svgWidth = svgWidth.slice(0, svgWidth.length - 2);
this.svgHeight = svgHeight.slice(0, svgHeight.length - 2) - this.margin;
}
_addAxisLabels() {
d3.selectAll('.line-chart__container svg .y-axis-label')
.remove();
d3.select('.line-chart__container svg')
.append('text')
.attr('class', 'y-axis-label')
.attr('x', '-72')
.attr('y', '12')
.attr('transform', 'rotate(-90)')
.text('REVENUE');
d3.select('.line-chart__container svg')
.append('text')
.attr('class', 'x-axis-label')
.text('TIME');
}
_buildBackground() {
this._addSvgContainer();
this._getSvgSizes();
let bars = [];
for (let i = 0; i < this.columns; i++) {
bars.push(this.svgHeight);
}
this.barsLayout = this.svg.append('g')
.attr('class', 'bars')
.attr('transform', 'translate(' + this.margin + ', 0)')
.selectAll('rect')
.data(bars)
.enter()
.append('rect');
this._addAxisLabels();
this._setBackgroundSizes();
}
_setBackgroundSizes() {
let availableBarWidth = (this.svgWidth - 2 * this.margin) / this.columns,
barWidth = availableBarWidth / 2;
this.barsLayout
.attr('fill', this.color)
.attr('y', this.margin)
.attr('height', function(d, i) {
return d;
})
.transition().duration(this.durationResizeAnimation)
.attr('width', barWidth)
.attr('x', function(d, i) {
return i * availableBarWidth;
});
d3.select('.line-chart__container svg .x-axis-label')
.transition().duration(this.durationResizeAnimation)
.attr('x', this.svgWidth - this.margin - 30)
.attr('y', this.svgHeight - (this.svgHeight) / 4 + this.margin + 14);
}
drawChart() {
this._buildBackground();
this._buildLegend();
this._buildNvGraph();
this._animateGraphs();
}
_buildNvGraph() {
this._tuneNvGraph();
nv.addGraph(() => {
this.svg.datum(this.data)
.transition().duration(0)
.call(this.lineChart);
nv.utils.windowResize(this.resizeBackground.bind(this));
nv.utils.windowResize(this.lineChart.update);
return this.lineChart;
});
}
_tuneNvGraph() {
this.lineChart = nv.models.lineChart()
.margin({top: this.margin, right: this.margin, bottom: 0, left: this.margin})
.useInteractiveGuideline(true)
.xDomain([0, 13.6])
.yDomain([-1.01, 3])
.showLegend(false)
.showYAxis(true)
.showXAxis(true)
.pointSize(5);
this.lineChart.tooltip.enabled(false);
this.lineChart.interactiveLayer.tooltip.enabled(false);
this.lineChart.xAxis
.showMaxMin(false)
.tickValues([0])
.tickFormat(d3.format('c'));
this.lineChart.yAxis
.showMaxMin(false)
.ticks(10)
.tickFormat(d3.format('c'));
}
_buildLegend() {
let legend = d3.select('.line-chart__container')
.append('div')
.attr('class', 'legend')
.selectAll('.legend__item')
.data(this.data)
.enter()
.append('div')
.attr('class', 'legend__item');
legend.append('div')
.attr('class', 'legend__mark pull-left')
.style('background-color', d => {
return d.color;
});
legend.append('div')
.attr('class', 'legend__text')
.text(d => {
return d.key;
});
}
resizeBackground() {
this._getSvgSizes();
this._setBackgroundSizes();
}
_animateGraphs() {
let i = 1;
this.timer = setInterval(() => {
this._calcAllGraphs(i);
this._drawNextStep(i);
i++;
this._checkEndOfAnimation(i);
}, 15);
}
_drawNextStep(i) {
if (i % this.drawStep == 0 || i == this.maxX) {
this.lineChart.update();
}
}
_checkEndOfAnimation(i) {
if (i == this.maxX + 1) {
this.lineChart.duration(this.durationResizeAnimation);
this.data[1].fillOpacity = 0.11;
this.lineChart.update();
clearInterval(this.timer);
}
}
_calcAllGraphs(i) {
this._calcFirstGraph(i);
this._calcSecondGraph(i);
this._calcThirdGraph(i);
}
_calcFirstGraph(i) {
const INTERVAL_1 = 28,
INTERVAL_2 = 71,
INTERVAL_3 = 110;
let graphAwesome = this.data[0].values;
if (i < INTERVAL_1) {
graphAwesome.push({x: i / 10, y: (.0343 * i * i - .67 * i) / 14});
} else {
if (i < INTERVAL_2) {
graphAwesome.push({x: i / 10, y: -(i - 71) * (i - 71) / 1026 + 2.378});
} else {
if (i < INTERVAL_3) {
graphAwesome.push({x: i / 10, y: -4 / (i - 43) + 2.53});
} else {
graphAwesome.push({x: i / 10, y: ((i - 114) * (i - 114) * (i - 114)) / 13000 + 2.476});
}
}
}
}
_calcSecondGraph(i) {
const INTERVAL_1 = 30,
INTERVAL_2 = 82;
let graphGood = this.data[1].values;
if (i < INTERVAL_1) {
graphGood.push({x: i / 10, y: (.03255 * i * i - .96 * i) / 16});
} else {
if (i < INTERVAL_2) {
graphGood.push({x: i / 10, y: (-.01055 * (i - 80.3) * (i - 80.3) + 27) / 15});
} else {
graphGood.push({x: i / 10, y: (((i / 2) - 45) * ((i / 2) - 45) * ((i / 2) - 45)) / 15000 + 1.805});
}
}
}
_calcThirdGraph(i) {
const INTERVAL_1 = 31,
INTERVAL_2 = 103;
let graphFail = this.data[2].values;
if (i < INTERVAL_1) {
graphFail.push({x: i / 10, y: (.02255 * i * i - .91 * i) / 13});
} else {
if (i < INTERVAL_2) {
graphFail.push({x: i / 10, y: .82 * Math.sin((i - 45) / 21)});
} else {
graphFail.push({x: i / 10, y: -(i - 130) * (i - 130) * (i - 130) / 64000});
}
}
}
}
let data = [
{
values: [{x: 0, y: 0}],
key: 'Awesome',
color: 'rgb(80, 150, 215)'
},
{
values: [{x: 0, y: 0}],
key: 'Good',
color: 'rgb(0, 188, 212)',
fillOpacity: 0.00001,
area: true
},
{
values: [{x: 0, y: 0}],
key: 'Fail',
color: 'rgb(255, 82, 82)'
}
];
let lineChartContainer = document.querySelector('.line-chart__container');
if (lineChartContainer) {
let lineChart = new LineChart(7, '#4a4a4a', 20, data, nv);
lineChart.drawChart();
}
}