var Chart = function(opts) { // load in arguments from config object this.data = opts.data; this.element = opts.element; this.bins = opts.bins; this.color = "steelblue" //default color // create the chart this.draw(); } Chart.prototype.draw = function() { // define width, height and paddings this.padding = 20; this.width = this.element.offsetWidth - (2*this.padding); this.height = (this.width / 2) - (2*this.padding); // set up parent element and SVG this.element.innerHTML = ''; var svg = d3.select(this.element).append('svg'); svg.attr('width', this.width + (2*this.padding)); svg.attr('height', this.height + (2*this.padding)); // we'll actually be appending to a element this.plot = svg.append('g') .attr("transform", "translate(" + this.padding + "," + this.padding + ")"); // create the other stuff this.createXScale(); this.generateHist(this.bins); //convert data to histogram layout this.createYScale(); //make the y scale based on that hist data. this.drawHist(); //actually draw the histogram this.addAxes(); //draw the axes this.setColor(this.color) //color the chart. } Chart.prototype.createXScale = function(){ // shorthand to save typing later var w = this.width, raw_data = this.data; this.xScale = d3.scale.linear() .domain(d3.extent(raw_data)) .range([0, w]); } Chart.prototype.generateHist = function(){ // Generate a histogram w/ uniformly-spaced bins. this.hist_data = d3.layout.histogram() .bins(this.xScale.ticks(this.bins)) (this.data); } Chart.prototype.createYScale = function(){ this.yScale = d3.scale.linear() .domain([0, d3.max(this.hist_data, function(d) { return d.y; })]) .range([this.height, 0]); } Chart.prototype.addAxes = function(){ var h = this.height, w = this.width; var xAxis = d3.svg.axis() .scale(this.xScale) .orient("bottom"); this.plot.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + h + ")") .call(xAxis) .selectAll("text") .attr("transform", "translate( 0 ," + -4 + ")"); } Chart.prototype.updateAxes = function(){ var h = this.height, w = this.width; var xAxis = d3.svg.axis() .scale(this.xScale) .orient("bottom"); this.plot.select(".x.axis").transition() .attr("transform", "translate(0," + h + ")") .call(xAxis) .selectAll("text") .attr("transform", "translate( 0 ," + -4 + ")"); } Chart.prototype.drawHist = function(){ //minumum observed data, needed for calculating bin width this.min = d3.min(this.data) var h = this.height, w = this.width, x = this.xScale, y = this.yScale hist_data = this.hist_data, bin_width = x(this.min + hist_data[0].dx); // A formatter for counts. var formatCount = d3.format(",.0f"); var hist = this.plot.selectAll(".bar") .data(this.hist_data) hist.transition() .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }) .each(function(){ d3.select(this).select("rect") //update the bars .transition() .attr("x", 1) .attr("width", bin_width - 1) .attr("height", function(d) { return h - y(d.y); }) // .attr("fill", this.color || "steelblue"); d3.select(this).select("text") //update the text .transition() .attr("x", bin_width / 2) .attr("y", -14) .text(function(d) { return d.y != 0 ? formatCount(d.y) : ""; }); }); hist.enter().append("g") .attr("class", "bar") .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }) .each(function(){ d3.select(this).append("rect") //draw the bars .attr("x", 1) .attr("width", bin_width - 1) .attr("height", function(d) { return h - y(d.y); }) // .attr("fill", this.color || "steelblue"); d3.select(this).append("text") //draw the text .attr("dy", ".75em") .attr("y", -14) .attr("x", bin_width / 2) .attr("text-anchor", "middle") .attr("fill", "#fff;") .text(function(d) { return formatCount(d.y); }); }); hist.exit() .remove() } // the following are "public methods" // which can be used by code outside of this file Chart.prototype.setColor = function(newColor) { this.plot.selectAll('rect') .style('fill',newColor); // store for use when redrawing this.color = newColor; } Chart.prototype.setData = function(newData) { this.data = newData; this.createXScale(); this.generateHist(this.bins); this.createYScale(); this.updateAxes(); this.drawHist(); this.setColor(this.color); }