score:-1

nice piece of code, but i found a little bug. it does lock your brush whenever s[1]-s[0] < 0.5, but if you keep pressed the resize and bring all your brush to the oposite direction, it starts "moving" the brush without any action (i.e. it doesn't behave as it should).

i am pretty sure i can come up with a reasonable solution. if so, i'll re-post it here.

(sorry to post it here as an answer, but as you've already answered it once, i cannot post as a comment, i guess).

score:0

here is an example of limiting the brush's minimum width as 100px and maximum width as 200ps. i added a few lines into d3.v4.js, for setting the limitation of the brush width.

added brush.limit([min, max]) for set the limitation:

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

break mouse move event in move() function:

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

(demo) (source code)

score:3

here's another strategy using d3.v4 an 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 brush selection size is too large when the user lets go of it, it animates back down to the specified maximum size (maxselectionsize). at that point, the 'end' event will fire again, with an acceptable selection size.

note the 0.49 scalar: this is required to prevent floating point / rounding errors that could cause an infinite loop if the brush is move()d to a size that is still too large.

score:5

i eventually solved it by redrawing the brush to its maximum allowed size when the size is exceeded:

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: http://bl.ocks.org/3691274

i'm still interested in reading better solutions.


More Query from same tag