Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@zmaril
Created July 11, 2012 22:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmaril/3094256 to your computer and use it in GitHub Desktop.
Save zmaril/3094256 to your computer and use it in GitHub Desktop.
Reusable backbone histogram

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.

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;
}
<!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>
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