如何修复 d3 中的多刷图表

How to fix a multiple brush chart in d3

我离得太近了,快要死了。我已经为一列生成了一个简单的画笔,它正在生成它完美设置的限制。问题是我想要多列 ['A'、'B'、'C'、'D'] 的多个画笔。我可以把它写四次,但我把它放在一个似乎不起作用的函数中。请查看下面的工作代码,我已经注释掉了不起作用的部分。我知道我需要以某种方式绑定数据并进行循环,但我该如何有效地做到这一点?

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = 960 - margin.left - margin.right,
  height = 180 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
  .domain(["A", "B", "C", "D"])
  .rangeBands([0, 200])

var y = d3.scale.linear()
  .range([height, 0])
  .domain([0, 100])

var xAxis = d3.svg.axis()
  .scale(x)

var svg = d3.select("#timeline").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


// define brush control element and its events
var brush = d3.svg.brush().y(y)
  .on("brushend", () => console.log('A Extent: ', brush.extent()))

// create svg group with class brush and call brush on it
var brushg = svg.append("g")
  .attr("class", "brush")
  .call(brush);

// set brush extent to rect and define objects height
brushg.selectAll("rect")
  .attr("x", x("A"))
  .attr("width", 20);

/*

var brush = (d) => {
    var brush = d3.svg.brush().y(y)    
                      .on("brushend", () => console.log(d, ' Extent: ', brush.extent()))
      
    var brushg = svg.append("g")
        .attr("class", "brush")
        .call(brush1);

    brushg.selectAll("rect")
        .attr("x", x("A"))
        .attr("width", 20);
 }
 */
.brush {
  fill: lightgray;
  fill-opacity: .75;
  shape-rendering: crispEdges;
}
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.6/d3.min.js'></script>
<div class="container">
  <div id="timeline"></div>
</div>

将画笔视为数据,因为它们映射到 x 轴上的每个序数值。使用 .enter 创建画笔并附加所有必要的功能。 .each 函数类似于调用,但分别在每个元素上运行。这对于包含画笔的生成非常有用。

xData = ["A", "B", "C", "D"];

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = 960 - margin.left - margin.right,
  height = 180 - margin.top - margin.bottom;


var x = d3.scale.ordinal()
  .domain(xData)
  .rangeBands([0, 200])

var y = d3.scale.linear()
  .range([height, 0])
  .domain([0, 100])

var xAxis = d3.svg.axis()
  .scale(x)

var svg = d3.select("#timeline").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  
const brushes = svg.selectAll('g.brush')
  .data(xData)
  .enter()
  .append('g')
  .attr('class', 'brush')
  .each(function(d) {
    const el = d3.select(this);
    
    const brush = d3.svg.brush().y(y).on("brushend", () => console.log(d, ' Extent: ', brush.extent()));
    
    el.call(brush);
    
    el.selectAll("rect")
      .attr("x", x(d))
      .attr("width", 20);
   });
.brush {
  fill: lightgray;
  fill-opacity: .75;
  shape-rendering: crispEdges;
}
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.6/d3.min.js'></script>
<div class="container">
  <div id="timeline"></div>
</div>