D3 2-dimensional brush non-removable

I made a scatter graph graph with a two-dimensional brush on the smaller graph below. This allows the user to dynamically view subzones of the full schedule. However, when I draw the area brush, it is no longer "movable" because the brush cannot be moved with the mouse in the same way as a 1-dimensional brush can be. There are 2D examples where the area of ​​2D brushes can be moved (for example, http://bl.ocks.org/mbostock/4343214 ), and the code for creating a two-dimensional brush is almost identical to 1D.

My question is, why does adding a second dimension eliminate the ability to move the brush?

Here is my code (where the external file is just the csv date and sale price):

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); } 
+4
source share
1 answer

The problem is here:

 xBrushGraph.append("g") .attr("class","x brush") .call(brush) .selectAll("rect") .attr("y", -6) .attr("height", height2 + 7); 

Here, after .call(brush) , you explicitly set the y and height attributes of all the rectangles inside the brush. These rectangles are used to determine which areas allow you to resize and drag the brush area.

For case 1D, setting the attributes 'y' and 'height' ensured that these values ​​made sense. The brush could not understand how much the brush should be, since the x scale was declared on it. In your case, you do not need to set the height of the brush field, since you provide it with a scale of y .

Removing the attribute settings solves the problem: http://jsfiddle.net/g7LGC/1/

+4
source

Source: https://habr.com/ru/post/1502492/


All Articles