D3.js: maximum brush size

Is there a way to limit the size of the brush, although the size is larger?

I only assembled a brush with size x, which can be moved and resized. I would like to be able to limit the extent to which it can be changed by the user (basically only to a certain point).

In the following example, the brush function stops updating when the brush becomes more than half the maximum. However, the brush itself can still be expanded. Is there any way to prevent this? Or is there a better way to handle this?

Thank you very much!

See this code in action here: http://bl.ocks.org/3691274 ( EDIT : this demo now works)

bar = function(range) { var x_range = d3.scale.linear() .domain([0, range.length]) .range([0, width]); svg.selectAll("rect.items").remove(); svg.selectAll("rect.items") .data(range) .enter().append("svg:rect") .attr("class", "items") .attr("x", function(d, i) {return x_range(i);}) .attr("y", 0) .attr("width", width/range.length-2) .attr("height", 100) .attr("fill", function(d) {return d}) .attr("title", function(d) {return d}); } var start = 21; bar(data.slice(0, start), true); var control_x_range = d3.scale.linear() .domain([0, data.length]) .range([0, width]); controlBar = svg.selectAll("rect.itemsControl") .data(data) .enter().append("svg:rect") .attr("class", "itemsControl") .attr("x", function(d, i) {return control_x_range(i);}) .attr("y", 110) .attr("width", width/data.length-2) .attr("height", 20) .attr("fill", function(d) {return d}); svg.append("g") .attr("class", "brush") .call(d3.svg.brush().x(d3.scale.linear().range([0, width])) .extent([0,1*start/data.length]) .on("brush", brush)) .selectAll("rect") .attr("y", 110) .attr("height", 20); function brush() { var s = d3.event.target.extent(); if (s[1]-s[0] < 0.5) { var start = Math.round((data.length-1)*s[0]); var end = Math.round((data.length-1)*s[1]); bar(data.slice(start,end)); }; } 
+5
source share
4 answers

In the end, I decided to redraw it with a brush to the maximum size when oversizing:

 function brush() { var s = d3.event.target.extent(); if (s[1]-s[0] < 0.5) { var start = Math.round((data.length-1)*s[0]); var end = Math.round((data.length-1)*s[1]); bar(data.slice(start,end)); } else {d3.event.target.extent([s[0],s[0]+0.5]); d3.event.target(d3.select(this));} } 

Demo version: http://bl.ocks.org/3691274

I'm still interested in reading the best solutions.

+5
source

Here's another strategy using d3.v4 - ES6:

 brush.on('end', () => { if (d3.event.selection[1] - d3.event.selection[0] > maxSelectionSize) { // selection is too large; animate back down to a more reasonable size let brushCenter = d3.event.selection[0] + 0.5 * (d3.event.selection[1] - d3.event.selection[0]); brushSel.transition() .duration(400) .call(brush.move, [ brushCenter - 0.49 * maxSelectionSize, brushCenter + 0.49 * maxSelectionSize ]); } else { // valid selection, do stuff } }); 

If the size of the brush selection is too large, when the user releases it, it will go down to the specified maximum size ( maxSelectionSize ). At this point, the 'end' event will light up again with an acceptable selection size.

Pay attention to scalar 0.49 : this is necessary to prevent floating point / rounding errors that can cause an infinite loop if the move() d brush is too large.

+1
source

The following is an example of limiting the minimum brush width to 100px and the maximum width to 200ps. I added a few lines to d3.v4.js to set a brush width limit.

Added brush.limit ([min, max]) parameter to set the limit:

 var _limit = null; brush.limit = function (l) { _limit = l; } 

Moving the mouse move event in the move () function:

 if (_limit && e1 - w1 < _limit[0]) { return; } 

( Demo ) ( Source Code )

0
source

Nice piece of code, but I found a little bug. It blocks your brush whenever s[1]-s[0] < 0.5 , but if you keep pressing the size and apply your entire brush to the opposite direction, it starts to โ€œmoveโ€ the brush without any action (i.e. She does not behave as she should).

I am sure I can come up with a reasonable solution. If so, I will translate it here.

(sorry to post it here as an answer, but, as you already answered once, I cannot post it as a comment, I think).

-1
source

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


All Articles