D3 笔刷事件——移动了哪个笔刷?左边那个还是右边那个?

D3 Brush events - which brush was moved? The left one or the right one?

希望标题说明了一切。

我正在处理 D3 笔刷移动事件。我想知道用户是移动了左画笔还是右画笔...?

我真的很想避免将鼠标位置存储在某处。

是否有相对简单的方法来解决这个问题..?

我能看到的最简单的方法:

// bind to at least start and end events
var brush = d3.brushX()
    .extent([[0, 0], [width, height]])
    .on("start brush end", brushmoved);

// handle it
var bs = "";
function brushmoved() {
  var s = d3.event.selection;

  if (d3.event.type === "start"){
    bs = d3.event.selection;
  } else if (d3.event.type === "end"){
    if (bs[0] !== s[0] && bs[1] !== s[1]) {
      console.log('moved both');
    } else if (bs[0] !== s[0]) {
      console.log('moved left');
    } else {
      console.log('moved right');
    }
  }

}


完整示例:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

circle {
  fill-opacity: 0.2;
  transition: fill-opacity 250ms linear;
}

circle.active {
  stroke: #f00;
}

</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var data = d3.range(800).map(Math.random);

var svg = d3.select("svg"),
    margin = {top: 194, right: 50, bottom: 214, left: 50},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleLinear().range([0, width]),
    y = d3.randomNormal(height / 2, height / 8);

var brush = d3.brushX()
    .extent([[0, 0], [width, height]])
    .on("start brush end", brushmoved);

g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x));

var circle = g.append("g")
    .attr("class", "circle")
  .selectAll("circle")
  .data(data)
  .enter().append("circle")
    .attr("transform", function(d) { return "translate(" + x(d) + "," + y() + ")"; })
    .attr("r", 3.5);

var gBrush = g.append("g")
    .attr("class", "brush")
    .call(brush);

var handle = gBrush.selectAll(".handle--custom")
  .data([{type: "w"}, {type: "e"}])
  .enter().append("path")
    .attr("class", "handle--custom")
    .attr("fill", "#666")
    .attr("fill-opacity", 0.8)
    .attr("stroke", "#000")
    .attr("stroke-width", 1.5)
    .attr("cursor", "ew-resize")
    .attr("d", d3.arc()
        .innerRadius(0)
        .outerRadius(height / 2)
        .startAngle(0)
        .endAngle(function(d, i) { return i ? Math.PI : -Math.PI; }));

gBrush.call(brush.move, [0.3, 0.5].map(x));

var bs = "";
function brushmoved() {
  var s = d3.event.selection;
  
  if (d3.event.type === "start"){
    bs = d3.event.selection;
  } else if (d3.event.type === "end"){
    if (bs[0] !== s[0] && bs[1] !== s[1]) {
      console.log('moved both');
    } else if (bs[0] !== s[0]) {
      console.log('moved left');
    } else {
      console.log('moved right');
    }
  }
  
  if (s == null) {
    handle.attr("display", "none");
    circle.classed("active", false);
  } else {
    var sx = s.map(x.invert);
    circle.classed("active", function(d) { return sx[0] <= d && d <= sx[1]; });
    handle.attr("display", null).attr("transform", function(d, i) { return "translate(" + s[i] + "," + height / 2 + ")"; });
  }
}

</script>