Skip to content

Instantly share code, notes, and snippets.

@ronsims2
Last active March 22, 2017 14:11
Show Gist options
  • Save ronsims2/a4f2d4ef7c6c6a325ae6ce6f587b0a22 to your computer and use it in GitHub Desktop.
Save ronsims2/a4f2d4ef7c6c6a325ae6ce6f587b0a22 to your computer and use it in GitHub Desktop.
D3 v4 dependent object for quick chart creation.
(function() {
var chart = function(config) {
this.svg = null;
this.g = null;
this.colors = config.colors || ['crimson', 'coral', 'yellow', 'seagreen', 'skyblue', 'violet', 'mediumorchid'];
this.height = config.height || 300;
this.width = config.width || 400;
this.marginTop = config.marginTop || 50;
this.marginBottom = config.marginBottom || 50;
this.marginLeft = config.marginLeft || 50;
this.marginRight = config.marginRight || 50;
this.ticksY = config.ticksY || 7;
this.ticksX = config.ticksX || 7;
this.createChart(config);
this.style = 'style=';
this.columnPrefix = config.columnPrefix || 'data_';
this.dataURL = config.dataURL || 'https://gist.githubusercontent.com/orangemantis/6097f7b1b5a4d82187c4171e1201ff01/raw/sample-data.csv';
this.data = null;
this.rangeX = d3.scaleTime().rangeRound([0, this.width]);
this.rangeY = d3.scaleLinear().rangeRound([this.height, 0]);
this.legend = null;
this.lineWidth = config.lineWidth || 1.5;
this.colorLegend = null;
this.ordinal = null;
this.labels = [];
this.labelColors = [];
if (!this.formatName) {
this.formatName = this.prototype._formatName;
}
};
chart.prototype.formatName = function(name) {
if (!name) {
return '';
}
var label = name.toString();
label = label.replace(this.columnPrefix, '').replace('_', ' ');
return label;
};
chart.prototype.addFormatName = function(formatter) {
if (typeof formatter === 'function') {
this.formatName = formatter;
console.log('Formatter added.');
}
}
chart.prototype.createChart = function(config) {
this.svg = d3.select('svg');
//override config
this.width = this.svg.attr('width') - this.marginLeft - this.marginRight,
this.height = this.svg.attr('height') - this.marginTop - this.marginBottom,
this.g = this.svg.append('g')
.attr('transform', 'translate(' + this.marginLeft + ',' + this.marginTop + ')');
};
chart.prototype.addStyle = function(configuration) {
if ((typeof configuration).toLowerCase() === 'object') {
}
};
//Date data should be formated 03-29-2017, 2 digit month, two digit day and 4 digit year!!!
chart.prototype.parseDate = d3.timeParse("%m-%d-%Y");
//Use css color
chart.prototype.addPlot = function(data, name, color) {
if (!data) {
data = this.data;
}
this.g.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', color)
.attr('stroke-linejoin', 'round')
.attr('stroke-linecap', 'round')
.attr('stroke-width', this.lineWidth)
.attr('data-legend', name)
.attr('d', this.createLine);
};
chart.prototype.splitData = function(data) {
var self = this;
var splitData = {};
data.forEach(function(row, i) {
if (i < data.length) { //Ignore the column row of data.
var colCount = 0;
for (var col in row) {
if (col.indexOf(self.columnPrefix) > -1) {
if (!splitData[col]) {
splitData[col] = [];
}
splitData[col].push({
date: row.date,
value: row[col],
color: self.colors[colCount]
});
colCount++;
}
}
}
});
return splitData;
};
chart.prototype.getRowMax = function(data) {
var max = 0;
var maxSet = false;
for (var col in data) {
if (col.indexOf(this.columnPrefix) > -1) {
if (!maxSet) {
max = data[col];
maxSet = true;
} else {
if (data[col] > max) {
max = data[col];
}
}
}
}
return max;
};
chart.prototype.flattenData = function(data) {
var self = this;
var flatData = [];
data.forEach(function(row) {
for (var col in row) {
if (col.indexOf(self.columnPrefix) > -1) {
flatData.push(row[col]);
}
}
});
flatData.push(0);
return flatData;
};
chart.prototype.init = function() {
var self = this;
this.createLine = d3.line()
.x(function(d) {
return self.rangeX(d.date);
})
.y(function(d) {
return self.rangeY(d.value);
});
d3.csv(this.dataURL, function(d) {
//format data
d.date = self.parseDate(d.date);
return d;
}, function(err, data) {
if (err) {
console.log('Error importing data:', err);
return false;
}
/**
* @todo Determine max-min values from various series.
*/
self.rangeX.domain(d3.extent(data, function(d) {
return d.date;
}));
self.rangeY.domain(d3.extent(self.flattenData(data), function(d) {
return d;
}));
self.g.append('g')
.attr('transform', 'translate(0,' + self.height + ')')
.call(d3.axisBottom(self.rangeX));
self.g.append('g')
.call(d3.axisLeft(self.rangeY))
.append('text')
.attr('fill', '#000000')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', "0.71em")
.attr('text-anchor', 'end')
.text("Occurances");
//Create the different data objects from 1
self.data = self.splitData(data);
var name = '';
for (var dataSet in self.data) {
name = self.formatName(dataSet);
self.labels.push(name);
self.labelColors.push(self.data[dataSet][0].color);
self.addPlot(self.data[dataSet], name, self.data[dataSet][0].color);
}
self.addLegend();
});
};
chart.prototype.addLegend = function() {
this.ordinal = d3.scaleOrdinal()
.domain(this.labels)
.range(this.labelColors);
this.colorLegend = d3.legendColor()
.scale(this.ordinal);
this.legend = this.svg.append('g')
.attr('class', 'legend')
.attr('transform', 'translate(' + this.marginLeft * 1.5 + ', ' + this.marginTop + ')')
.call(this.colorLegend);
}
window.plomni = chart;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment