简体   繁体   中英

Why does D3's brush start event interfere with later brush events?

In the minimal example below, the brush is used to select circles (assigning them the selected class) and then emptied at the end. Without the start event, the selection augments with each brush action as expected. The brushstart() function is added, however, to clear at the start of each brush action unless the ctrl key is pressed. Somehow, it ends up wiping out the selection that takes place later during the brush event as well. You can see the circles get selected with the change of color during brushing, but when the mouse is released, they all become deselected.

How can I fix this? What really puzzles me is how brushstart() can cancel the selections made by brushmove() .

 'use strict' var random = d3.randomUniform(0.1, 0.9), points = d3.range(50).map(function() { return [random(), random()] }); var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); var x = d3.scaleLinear() .domain([0, 1]) .range([0, width]), y = d3.scaleLinear() .domain([0, 1]) .range([height, 0]); var brush = d3.brush() .on('start', brushstart) .on('brush', brushmove) .on("end", brushended); var circles = svg.selectAll("circle") .data(points) .enter().append("circle") .attr("cx", function(d) { return x(d[0]); }) .attr("cy", function(d) { return y(d[1]); }) .attr("r", 2.5) .attr("fill", 'steelblue'); svg.append("g") .attr("class", "brush") .call(brush); function brushstart() { // works as expected w/o the following line if (!d3.event.ctrlKey) { circles.classed('selected', false) } } function brushmove() { var s = d3.event.selection; if (s) { var newlySelected = circles.filter(function(d) { return s[0][0] <= x(d[0]) && x(d[0]) <= s[1][0] && s[0][1] <= y(d[1]) && y(d[1]) <= s[1][1]; }); newlySelected.classed('selected', true); } } function brushended() { var s = d3.event.selection; if (s) { svg.select(".brush").call(brush.move, null); } }
 .selected { fill: crimson }
 <svg width="300" height="300"></svg> <script src="https://d3js.org/d3.v4.min.js"></script>

brushstart is called from brushend:

if (s) {
    svg.select(".brush").call(brush.move, null);
  }

Maybe you could check the selection in brushstart:

function brushstart() {
  // works as expected w/o the following line
  if (!d3.event.ctrlKey && d3.event.selection) {
    circles.classed('selected', false)
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM