d3 v4 + react + es6 + crossfilter:Selection.exit()。remove()无法正常工作

时间:2016-07-28 07:35:03

标签: javascript d3.js reactjs ecmascript-6 crossfilter

我正在使用crossfilter.jsd3.js v4使用ES6样式的React来尝试使用上下文刷制来创建维度图表。基本上,我拿了this example并将其转换为ES6。

我遇到的问题是selection.exit().remove()无效,因此在每次重绘时,会有越来越多的圆圈附加到svg g元素上。创建画笔时会触发重绘。我通过运行检查

selection.exit()
  .attr('class', d => {
    console.log('anything');
    return 'anything';
  })
  .remove();

但没有输出,所以我认为我的数据选择无效。

以下是上下文:

componentDidMount() {
  const el = ReactDOM.findDOMNode(this); // the mounted svg element

  const svg = d3.select(el)
    .attr('width', 300)
    .attr('height', 500);

  const g = svg.append('g')
    .attr('transform', 'translate(32,32)');

  let circles = g.append('g')
    .selectAll('circle');

  const brushGroup = g.append('g')
    .attr('class', 'brush')
    .call(brush);

  function redraw() {
    const all = group.all(); // crossfilter group returns an array

    xAxisGroup.call(xAxis);
    yAxisGroup.call(yAxis);

    circles = circles.data(all, d => d); // keyFn for data constancy

    circles.enter().append('circle')
      .attr('r', radius)
      .attr('cx', plotX) // radius + plotX/Y are simple curry functions
      .attr('cy', plotY);

    circles.exit().remove(); // not working!!
  }

  redraw();
}

我也知道v4中d3-selection的这种变化,但我不能确定哪些行是update,哪些是update + enter

非常感谢任何帮助。谢谢!

1 个答案:

答案 0 :(得分:1)

我怀疑问题是两件事之一。可能在下面#1。用一个可以用来测试内容的工作示例来说,有点难以分辨,但是你走了:

  1. 我认为selectAlldata联接应该在redraw函数中一起发生。因为您从不重做重绘函数中的selectAll,所以您的选择将永远不会包含任何元素。如果您检查enter函数中的exitredraw选项,则enter选项将始终包含所有数据点,因为基础选择为空。

  2. 您的数据键函数返回一个对象。由于该对象是Crossfilter的group.all的结果,因此它们应该通过引用进行比较,但是circles.data(all, d => d.key)会更安全。

  3. 解决方案应该是:

    componentDidMount() {
      const el = ReactDOM.findDOMNode(this); // the mounted svg element
    
      const svg = d3.select(el)
        .attr('width', 300)
        .attr('height', 500);
    
      const g = svg.append('g')
        .attr('transform', 'translate(32,32)');
    
      let circlesGroup = g.append('g'); // Just hang on to the group
    
      const brushGroup = g.append('g')
        .attr('class', 'brush')
        .call(brush);
    
      function redraw() {
        const all = group.all(); // crossfilter group returns an array
    
        xAxisGroup.call(xAxis);
        yAxisGroup.call(yAxis);
    
        let circles = circlesGroup // Do the selection and data join here
          .selectAll('circle')
            .data(all, d => d.key); // Have the key function return a key, not an object
    
        circles.enter().append('circle')
          .attr('r', radius)
          .attr('cx', plotX) // radius + plotX/Y are simple curry functions
          .attr('cy', plotY);
    
        circles.exit().remove();
      }
    
      redraw();
    }