Home > Software engineering >  d3.js I have multiple brush area. How can I cancel brush region in other area when I brush a new reg
d3.js I have multiple brush area. How can I cancel brush region in other area when I brush a new reg

Time:12-08

I have a svg, and many gs in this svg.

for (let j = 0; j < 3; j  ) {
    let rx = 400 * j, ry = 100, rw = 300, rh = 300;
    let g = svg.append("g")
        .attr("x", rx).attr("y", ry)
        .attr("width", rw).attr("height", rh);
}

And I create a brush for each g:

for (let j = 0; j < 3; j  ) {
    let rx = 400 * j, ry = 100, rw = 300, rh = 300;
    let g = svg.append("g")
        .attr("x", rx).attr("y", ry)
        .attr("width", rw).attr("height", rh);

    g.call(d3.brush()
        .extent([[rx,ry], [rx rw,ry rh]])
        .on("start brush", function (e){
            svg.selectAll("g").call(d3.brush().clear);
            let extent = e.selection;
            //do something
            })
    );
}

The codes above cause a error because:
Uncaught RangeError: Maximum call stack size exceeded
How can I do this in other way?\

let width = 2000;
let height = 1200;
let svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

for (let j = 0; j < 3; j  ) {
  let rx = 400 * j,
    ry = 100,
    rw = 300,
    rh = 300;
  let g = svg.append("g")
    .attr("x", rx).attr("y", ry)
    .attr("width", rw).attr("height", rh);

  g.append("rect")
    .attr("x", rx).attr("y", ry)
    .attr("width", rw).attr("height", rh)
    .attr("fill", "white")
    .attr("stroke", "black");

  g.call(d3.brush()
    .extent([
      [rx, ry],
      [rx   rw, ry   rh]
    ])
    .on("start brush", function(e) {
      svg.selectAll("g").call(d3.brush().clear);
      let extent = e.selection;
    })
  );
}
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

brush and start are two different events, and there will never be a brush that is not preceded by a start, so you can omit the brush here. That way, the code is not constantly triggering itself and the infinite loop recursion is avoided:

let width = 2000;
let height = 1200;
let svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

for (let j = 0; j < 3; j  ) {
  let rx = 400 * j,
    ry = 100,
    rw = 300,
    rh = 300;
  let g = svg.append("g")
    .attr("x", rx).attr("y", ry)
    .attr("width", rw).attr("height", rh);

  g.append("rect")
    .attr("x", rx).attr("y", ry)
    .attr("width", rw).attr("height", rh)
    .attr("fill", "white")
    .attr("stroke", "black");

  g.call(d3.brush()
    .extent([
      [rx, ry],
      [rx   rw, ry   rh]
    ])
    .on("start", function(e) {
      svg.selectAll("g").call(d3.brush().clear);
      let extent = e.selection;
    })
  );
}
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related