Flavio
Flavio

Reputation: 1587

D3 updating brush's scale doesn't update brush

What I want to create is a zoomable, brushable timeline in D3 version 3.5.6. For now I'm not using D3's zoom behavior but just two zoom buttons. My problem is the following: When a button is clicked, I update the scale and redraw the axis as well as the brush. For some reason the brush doesn't update the extent rectangle and the handles but just the background. I know that I'm not actually updating the .extent() of the brush. But isn't the brush supposed to update when the scale was changed?

Here's the relevant portion of the code. The rest can be found in this fiddle.

document.getElementById('in').addEventListener('click', zoom.bind(null, .1));
document.getElementById('out').addEventListener('click', zoom.bind(null, -.1));

function zoom(step) {
  var offset;

  zoomScale += step;

  if(zoomScale < 1)
    zoomScale -= step;

  offset = (zoomScale * width - width) / 2;

  // updating the scale
  xScale
    .range([-offset, width + offset]);

  // redrawing the brush which doesn't seem to have effect I expected
  brushGroup
    .call(brush);

  // redrawing the axis which works fine
  xAxisGroup
    .transition()
    .call(xAxis);      
}

Thanks a lot!

Upvotes: 5

Views: 2659

Answers (3)

maia
maia

Reputation: 4370

I had the same problem, and fixed it by deleting the brush group and calling it again.

Before graph resizing:

var brush = d3.brushX().extent([[0, 0], [graph_dim.w, graph_dim.h]]).on("end", brushended);
graphContent.append("g").attr("class", "brush").call(brush);

After graph resizing:

// update graph height 
graph_dim.h = my_new_graph_height;

// update brush extent
brush.extent([[0, 0], [graph_dim.w, graph_dim.h]]);
graphDIV.select(".brush").remove();
graphContent.append("g").attr("class", "brush").call(brush);

Probably not the best way, but it works :-)

NOTE that if you have mouse events on the same graph, they will no longer be accessible (the brush will "cover" them) -- see this answer.

Upvotes: 0

herrstucki
herrstucki

Reputation: 258

Apparently you need to reset the brush's extent, so the internal xExtent and yExtent variables are reset. Seems like a bug to me.

brush.extent(brush.extent());

https://jsfiddle.net/azksfjjw/6/

Upvotes: 6

Shailendra Sharma
Shailendra Sharma

Reputation: 6992

I caught the problem in your zoom function you re define xScale range as

 xScale
    .range([-offset, width + offset]); 

After this you need to pass it here

brush = d3.svg.brush()
          .x(xScale) // This need new Values 
          .extent([.1, .6]),

Than after you can call to re draw your time line

 brushGroup
        .call(brush);

here the fiddle https://jsfiddle.net/azksfjjw/4/

Upvotes: 2

Related Questions