I have made a scatterplot graph with a 2-dimensional brush in a smaller graph underneath. This enables the user to dynamically look at sub-areas of the full graph. However, when I draw an area brush, it is no longer "moveable," in that the brush cannot be moved around with the mouse in the way that the 1-dimensional brush can be. There are 2D examples in which the 2D brush area can be moved around (for example http://bl.ocks.org/mbostock/4343214), and the code to create the 2D brush is virtually identical to the 1D.
My question is why adding the second dimension removes the ability to move the brush around?
Here is my code (where the external file is just a csv of date and sales prices):
var margin = {top: 25, right: 10, bottom: 200, left: 75},
margin2 = {top:350, right: 10, bottom: 30, left: 75},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse,
commasFormatter = d3.format(",.0f");
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(-height,0,0),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left").tickFormat(function(d) { return "$" + commasFormatter(d); }).tickSize(-width,0,0),
yAxis2 = d3.svg.axis().scale(y2).orient("left").tickFormat(function(d) { return "$" + commasFormatter(d); });
var brush = d3.svg.brush()
.x(x2)
.y(y2)
.on("brush", brushed);
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath") //defines clipping mask around large graph
.attr("id","clip")
.append("rect") //mask shape is rectangle
.attr("width", width) //mask width is drawable width of large graph
.attr("height", height); //mask height is drawable height of large graph
var largeGraph = svg.append("g")
.attr("transform","translate("+margin.left+","+margin.top+")");
var xBrushGraph = svg.append("g")
.attr("transform", "translate("+margin2.left+","+margin2.top+")");
//BRING IN THE INITIAL DATA
d3.csv("6MonthPracticeData.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.price = +d.price;
});
x.domain(d3.extent(data.map(function(d) { return d.date; })));
y.domain([0, d3.max(data.map(function(d) { return d.price; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
largeGraph.append("g").attr("class","dot")
.selectAll("circle")
.data(data).enter()
.append("circle")
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.price); })
.attr("r",5)
.attr("clip-path", "url(#clip)");
largeGraph.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
largeGraph.append("g")
.attr("class", "y axis")
.call(yAxis);
largeGraph.append("text")
.attr("transform", "rotate(-90)")
.attr("y",0 - margin.left)
.attr("x", 0 - (height/2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Sale Price");
xBrushGraph.append("g").attr("class","smalldot")
.selectAll("circle")
.data(data).enter()
.append("circle")
.attr("cx", function(d) { return x2(d.date); })
.attr("cy", function(d) { return y2(d.price); })
.attr("r",2.5);
xBrushGraph.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,"+height2+")")
.call(xAxis2);
xBrushGraph.append("g")
.attr("class", "y axis")
.call(yAxis2);
//rotated y-axis label
xBrushGraph.append("text")
.attr("transform", "rotate(-90)")
.attr("y",0 - margin2.left)
.attr("x", 0 - (height2/2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Sale Price");
xBrushGraph.append("g")
.attr("class","x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
xBrushGraph.append("text")
.attr("x", width/2)
.attr("y", height2+25)
.style("text-anchor", "middle")
.text("Sale Date");
});
function brushed() {
var extent = brush.extent();
x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent [1][0] ]);
y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent [1][1] ]);
largeGraph.selectAll("circle")
.attr("cx",function(d) { return x(d.date); })
.attr("cy",function(d) { return y(d.price); });
largeGraph.select(".x.axis").call(xAxis);
largeGraph.select(".y.axis").call(yAxis);
}