Skip to content

Commit

Permalink
Make visualisations individual views
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Metson committed Nov 8, 2011
1 parent 5ccfd62 commit 06530cf
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 162 deletions.
345 changes: 185 additions & 160 deletions backbone-d3.js
@@ -1,177 +1,202 @@
(function(){
Backbone.d3 = {
PlotView: Backbone.View.extend(
{
initialize: function(collection, settings) {
_.bindAll(this);
this.collection = collection;
this.collection.bind('change', this.redraw);
this.collection.bind('add', this.redraw);
this.collection.bind('remove', this.redraw);
this.collection.bind('reset', this.draw);
var PlotView = Backbone.View.extend({
initialize: function(collection, settings) {
_.bindAll(this);
this.collection = collection;
this.collection.bind('change', this.redraw);
this.collection.bind('add', this.redraw);
this.collection.bind('remove', this.redraw);
this.collection.bind('reset', this.draw);

this.settings = settings || {};
var divname = this.settings.div || "#plot";
this.div = d3.select(divname)
this.duration = this.settings.duration || 500;
this.settings = settings || {};
var divname = this.settings.div || "#plot";
this.div = d3.select(divname)
this.duration = this.settings.duration || 500;

this.collection.fetch();
// TODO: make the chart a member var of the View
// for easier access/fine grained control
},
draw: function() {
// Draw the plot
if (this.collection.plotdata().length > 0) {
this[this.collection.plottype]({newPlot: true});
//this.caption();
}
},
redraw: function(){
// transition the plot
this[this.collection.plottype]({newPlot: false});
},
pie: function(options){
var data = this.collection.plotdata();
var m = 10, r = 100, z = d3.scale.category20c();
if (options.newPlot) {
var svg = this.div.selectAll("svg")
.data([data])
.enter().append("svg:svg")
.attr("width", (r + m) * 2)
.attr("height", (r + m) * 2)
.append("svg:g")
.attr("transform", "translate(" + (r + m) + "," + (r + m) + ")");
svg.selectAll("path")
.data(d3.layout.pie())
.enter().append("svg:path")
.attr("d", d3.svg.arc()
.innerRadius(r / 8)
.outerRadius(r))
.style("fill", function(d, i) { return z(i);});
} else {
var svg = d3.select("#plot").selectAll("svg");
svg.data([data]);
var pie = svg.selectAll("path");
pie.data(d3.layout.pie());
pie.transition()
.attr("d", d3.svg.arc()
.innerRadius(r / 8)
.outerRadius(r))
.style("fill", function(d, i) { return z(i);});
}
},
bar: function(options){
var w = options.w || 20;
var h = options.h || 80;
var data = this.collection.plotdata();
this.collection.fetch();
// TODO: make the chart a member var of the View
// for easier access/fine grained control
},
draw: function() {
// Draw the plot
if (this.collection.plotdata().length > 0) {
this.plot({
newPlot: true
});
//this.caption();
}
},
redraw: function() {
// transition the plot
this.plot({
newPlot: false
});
},
plot: function() {
if (console){ console.log("Not implemented in base class"); }
return;
} // ,
// caption: function(){
// if (this.collection.caption){
// var caption;
// if (Markdown) {
// var converter = Markdown.getSanitizingConverter();
// caption = converter.makeHtml(this.collection.caption);
// } else {
// caption = this.collection.caption;
// }
// d3.select("#plot").write(caption);
// }
// }
});

var scale = d3.round(h/_.max(data, function(d){return d.y;}).y);
(function() {
Backbone.d3 = {
PlotView: PlotView,
PieView: PlotView.extend(
{
plot: function(options) {
var data = this.collection.plotdata();
var m = 10,
r = 100,
z = d3.scale.category20c();
if (options.newPlot) {
var svg = this.div.selectAll("svg")
.data([data])
.enter().append("svg:svg")
.attr("width", (r + m) * 2)
.attr("height", (r + m) * 2)
.append("svg:g")
.attr("transform", "translate(" + (r + m) + "," + (r + m) + ")");
svg.selectAll("path")
.data(d3.layout.pie())
.enter().append("svg:path")
.attr("d", d3.svg.arc()
.innerRadius(r / 8)
.outerRadius(r))
.style("fill",
function(d, i) { return z(i); });
} else {
var svg = d3.select("#plot").selectAll("svg");
svg.data([data]);
var pie = svg.selectAll("path");
pie.data(d3.layout.pie());
pie.transition()
.attr("d", d3.svg.arc()
.innerRadius(r / 8)
.outerRadius(r))
.style("fill", function(d, i) { return z(i); });
}
}
}),
BarView: PlotView.extend(
{
plot: function(options) {
var w = options.w || 20;
var h = options.h || 80;
var data = this.collection.plotdata();

var yval = function(d){return h - scale * d.y - .5;};
var scale = d3.round(h / _.max(data, function(d) { return d.y; }).y);

var x = d3.scale.linear()
.domain([0, 1])
.range([0, w]);
var yval = function(d) { return h - scale * d.y - .5; };

var y = d3.scale.linear()
.domain([0, 100])
.rangeRound([0, h]);
var x = d3.scale.linear()
.domain([0, 1])
.range([0, w]);

if (options.newPlot) {
var chart = this.div.append("svg:svg")
.attr("class", "chart")
.attr("width", w * data.length - 1)
.attr("height", h);
var y = d3.scale.linear()
.domain([0, 100])
.rangeRound([0, h]);

chart.selectAll("rect")
.data(data)
.enter().append("svg:rect")
.attr("x", function(d, i) { return x(i) - .5; })
.attr("y", function(d) { return yval(d) })
.attr("width", w)
.attr("height", function(d) { return scale * d.y; });
if (options.newPlot) {
var chart = this.div.append("svg:svg")
.attr("class", "chart")
.attr("width", w * data.length - 1)
.attr("height", h);

chart.append("svg:line")
.attr("x1", 0)
.attr("x2", w * (1 + data.length))
.attr("y1", h - .5)
.attr("y2", h - .5)
.attr("stroke", "#000");
chart.selectAll("rect")
.data(data)
.enter().append("svg:rect")
.attr("x", function(d, i) { return x(i) - .5; })
.attr("y", function(d) { return yval(d) })
.attr("width", w)
.attr("height",
function(d) { return scale * d.y; });

chart.append("svg:line")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", 0)
.attr("y2", h - .5)
.attr("stroke", "#000");
} else if (this.collection.scrolling) {
var chart = this.div.selectAll("svg");
var rect = chart.selectAll("rect")
.data(data, function(d) { return d.x; });
chart.append("svg:line")
.attr("x1", 0)
.attr("x2", w * (1 + data.length))
.attr("y1", h - .5)
.attr("y2", h - .5)
.attr("stroke", "#000");

rect.enter().insert("svg:rect", "line")
.attr("x", function(d, i) { return x(i+1) - .5; })
.attr("y", function(d) { return yval(d) })
.attr("width", w)
.attr("height", function(d) { return scale * d.y; })
.transition()
.duration(this.duration)
.attr("x", function(d, i) { return x(i) - .5; });
chart.append("svg:line")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", 0)
.attr("y2", h - .5)
.attr("stroke", "#000");
} else if (this.collection.scrolling) {
var chart = this.div.selectAll("svg");
var rect = chart.selectAll("rect")
.data(data, function(d) { return d.x; });

rect.transition()
.duration(this.duration)
.attr("x", function(d, i) { return x(i) - .5; })
.attr("y", function(d, i) { return yval(d) })
.attr("height", function(d) { return scale * d.y; });
rect.enter().insert("svg:rect", "line")
.attr("x", function(d, i) { return x(i + 1) - .5; })
.attr("y", function(d) { return yval(d) })
.attr("width", w)
.attr("height", function(d) { return scale * d.y; })
.transition()
.duration(this.duration)
.attr("x", function(d, i) { return x(i) - .5; });

rect.exit()
.transition()
.duration(this.duration)
.attr("x", function(d, i) { return x(i - 1) - .5; })
.attr("y", function(d) { return yval(d) })
.attr("height", function(d) { return scale * d.y; })
.remove();
} else {
this.div.selectAll("rect")
.data(data)
.transition()
.duration(this.duration)
.attr("y", function(d) { return yval(d) })
.attr("height", function(d) { return scale * d.y; });
}
} // ,
// caption: function(){
// if (this.collection.caption){
// var caption;
// if (Markdown) {
// var converter = Markdown.getSanitizingConverter();
// caption = converter.makeHtml(this.collection.caption);
// } else {
// caption = this.collection.caption;
// }
// d3.select("#plot").write(caption);
// }
// }
}
),
PlotCollection: Backbone.Collection.extend(
{
initialize: function(models, plottype, settings) {
_.bindAll(this);
this.settings = settings || {};
this.plottype = plottype || "bar";
this.scrolling = this.settings.scrolling || false;
this.reset(models);
},
plotdata: function(){
var data = [];
this.forEach(function(datapoint) {
data.push(datapoint.get('value'));
}
)
return data;
rect.transition()
.duration(this.duration)
.attr("x", function(d, i) { return x(i) - .5; })
.attr("y", function(d, i) { return yval(d) })
.attr("height", function(d) { return scale * d.y; });

rect.exit()
.transition()
.duration(this.duration)
.attr("x", function(d, i) { return x(i - 1) - .5; })
.attr("y",function(d) { return yval(d) })
.attr("height", function(d) { return scale * d.y; })
.remove();
} else {
this.div.selectAll("rect")
.data(data)
.transition()
.duration(this.duration)
.attr("y", function(d) { return yval(d) })
.attr("height", function(d) { return scale * d.y; });
}
}
}),
PlotCollection: Backbone.Collection.extend({
initialize: function(models, plottype, settings) {
_.bindAll(this);
this.settings = settings || {};
this.plottype = plottype || "bar";
this.scrolling = this.settings.scrolling || false;
this.reset(models);
},
plotdata: function() {
var data = [];
this.forEach(function(datapoint) {
data.push(datapoint.get('value'));
}
)
return data;
}
}),
getView: function(collection, settings) {
// Factory function to load a plot view by collection type
settings = settings || {};
if (collection.plottype == 'bar') {
return new this.BarView(collection, settings);
} else if (collection.plottype == 'pie') {
return new this.PieView(collection, settings);
}
)
}
}
})();
4 changes: 2 additions & 2 deletions examples/bar.html
Expand Up @@ -44,7 +44,7 @@

var series1 = new DataSeries();

var plot1 = new Backbone.d3.PlotView(series1, {div:'#plot1'});
var plot1 = Backbone.d3.getView(series1, {div:'#plot1'});
series1.reset([
new DataPoint({x:1, y:6, id:1}),
new DataPoint({x:2, y:4, id:2}),
Expand All @@ -63,7 +63,7 @@
var series2 = new DataSeries();
series2.scrolling = true;

var plot2 = new Backbone.d3.PlotView(series2, {div:'#plot2'});
var plot2 = Backbone.d3.getView(series2, {div:'#plot2'});
series2.reset([
new DataPoint({x:1, y:5, id:1}),
new DataPoint({x:2, y:4, id:2}),
Expand Down

0 comments on commit 06530cf

Please sign in to comment.