Accepted answer

Took me a while to realise that all I'm doing when moving the brush is moving the rects. And what controls the rects' position? The transform attribute. So I took the same transform call from the rect drawing part of my code and put it in the brush code, and voila, it works. So my final brushed function looks like this:

function brushed() {
                    if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
                    var s = d3.event.selection || xZoom.range();
                    x.domain(, xZoom));
                    svg2.selectAll(".data-rect").attr("transform", function(d) { 
                        return 'translate('+ x( + ',' + y(d[1]) + ')';
          ".firstline").attr("d", cumulativeLine);
          ".zoom").call(zoom.transform, d3.zoomIdentity
                        .scale(width / (s[1] - s[0]))
                        .translate(-s[0], 0));

Related Query

More Query from same tag