An example of how to use backbone and d3 together to create reusable charts for collections. See here for more information about the motivation and implementation of this particular chart.
Created
July 11, 2012 22:44
-
-
Save zmaril/3094256 to your computer and use it in GitHub Desktop.
Reusable backbone histogram
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
font: 10px sans-serif; | |
} | |
#main { | |
position: absolute; | |
width: 90%; | |
} | |
#main #text { | |
padding-bottom: 10px; | |
} | |
.bar rect { | |
fill: steelblue; | |
shape-rendering: crispEdges; | |
} | |
.bar text { | |
fill: #fff; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<head> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="index.css"> | |
</head> | |
<body> | |
<div id="main"> | |
<div id="booksHistogram"></div> | |
</div> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> | |
<script src="http://d3js.org/d3.v2.min.js"></script> | |
<script src="http://underscorejs.org/underscore-min.js"></script> | |
<script src="http://backbonejs.org/backbone-min.js"></script> | |
<script src="index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Book, Books, BooksCollection, BooksHistogram, Histogram, IrwinHall, average, i, updateCollection; | |
Book = Backbone.Model; | |
BooksCollection = Backbone.Collection.extend({ | |
model: Book | |
}); | |
IrwinHall = function(n) { | |
return _.chain(d3.range(n)).map(function() { | |
return Math.random(); | |
}).reduce(function(a, b) { | |
return a + b; | |
}).value() / n; | |
}; | |
average = 250; | |
Books = new BooksCollection((function() { | |
var _results; | |
_results = []; | |
for (i = 0; i < 1000; i++) { | |
_results.push({ | |
pages: Math.round(IrwinHall(20) * average) | |
}); | |
} | |
return _results; | |
})()); | |
Histogram = Backbone.View.extend({ | |
initialize: function() { | |
var _this = this; | |
this.vis = {}; | |
this.vis.svg = d3.select(this.el).append("svg").attr("height", this.options.height).attr("width", this.options.width); | |
this.vis.svg.attr("class", "histogram"); | |
this.vis.bars = this.vis.svg.append("g").attr("id", "bars"); | |
this.vis.axis = this.vis.svg.append("g").attr("id", "axis").attr("class", "x axis"); | |
this.d3 = {}; | |
this.d3.hist = d3.layout.histogram().value(this.options.value); | |
this.render(); | |
this.collection.on("add", function() { | |
return _this.render(); | |
}); | |
return this.collection.on("remove", function() { | |
return _this.render(); | |
}); | |
}, | |
render: function() { | |
var bars, delta, first, labels, last, newBars, x, xAxis, y, | |
_this = this; | |
window.bins = this.d3.hist(this.collection.models); | |
first = bins[0]; | |
last = bins[bins.length - 1]; | |
x = d3.scale.linear().domain([0, 250]).range([0, this.options.width]); | |
y = d3.scale.linear().domain([ | |
0, d3.max(bins, function(d) { | |
return d.y; | |
}) | |
]).range([this.options.height, 20]); | |
bars = this.vis.bars.selectAll("g").data(bins); | |
newBars = bars.enter().append('g').attr("class", "bar").attr("transform", function(d) { | |
return "translate(" + (x(d.x)) + "," + (y(d.y) - 20) + ")"; | |
}); | |
newBars.append("rect"); | |
delta = 1000; | |
bars.transition().duration(delta).attr("transform", function(d) { | |
return "translate(" + (x(d.x)) + "," + (y(d.y) - 20) + ")"; | |
}); | |
bars.select("rect").transition().duration(delta).attr("width", x(bins[0].dx) - 1).attr("height", function(d) { | |
return _this.options.height - y(d.y); | |
}); | |
labels = newBars.append("text"); | |
bars.select("text").transition().duration(delta).attr("dy", ".75em").attr("y", 6).attr("x", x(bins[0].dx) / 2).attr("text-anchor", "middle").text(function(d) { | |
return d.y; | |
}); | |
xAxis = d3.svg.axis().scale(x).orient("bottom"); | |
return this.vis.axis.attr("transform", "translate(0," + (this.options.height - 20) + ")").call(xAxis); | |
}, | |
remove: function() { | |
return this.vis.svg.remove(); | |
} | |
}); | |
BooksHistogram = null; | |
updateCollection = function() { | |
var i; | |
Books.add((function() { | |
var _results; | |
_results = []; | |
for (i = 1; i < 50; i++) { | |
_results.push({ | |
pages: Math.round(IrwinHall(i) * average) | |
}); | |
} | |
return _results; | |
})()); | |
Books.remove(Books.models.slice(1, 50)); | |
return average = Math.random() * 250; | |
}; | |
$(document).ready(function() { | |
BooksHistogram = new Histogram({ | |
collection: Books, | |
el: $("#booksHistogram"), | |
value: function(d) { | |
return d.get("pages"); | |
}, | |
height: 500, | |
width: 960 | |
}); | |
return setInterval(updateCollection, 1000); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment