【问题标题】:d3 v4 + react + es6 + crossfilter: Selection.exit().remove() not workingd3 v4 + react + es6 + crossfilter:Selection.exit().remove() 不起作用
【发布时间】:2016-07-28 07:35:03
【问题描述】:

我将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

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • exit 选择是,在将数据绑定到选择之后,所有那些没有数据引用它们的元素。现在仔细看看你的let circles:它们没有绑定任何数据。您必须正确定义输入、更新和退出选择。现在它们的定义不正确。
  • 当我设置 circles = circles.data(all, d => d).. 时会怎样,这不会创建正确的连接选择因此 circles.enter()circles.exit()
  • 您的圈子数据是否有唯一 ID,例如 circles = circles.data(all, d => d.id)
  • @John,是的,确实如此:是那个不仔细看的人,我读到了circles.data,实际上是circles = circles.data。继续:尝试从圈子中删除 append("g"),我的意思是,将其放在其他任何地方,而不是在 let circles 分配中。
  • @Gerardo 我尝试删除嵌套的g,但没有帮助。我确实需要父 g 因为有兄弟 gs.. DOM 结构看起来像 svg --> g --> g, g, g, g

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


【解决方案1】:

我怀疑问题是两件事之一。可能是下面的#1。如果没有一个工作示例来测试它,这有点难以判断,但是你去吧:

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

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

解决方案应该是:

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();
}

【讨论】:

  • 我觉得我尝试了所有模式,除了那个!这主要是因为在手动调用redraw() 之后,我将圆圈与图表一起导出(参见代码笔),但事实证明我唯一使用导出图表的目的是redraw(),所以这很有意义!现在,如果我能让我的 d3 v4 直方图工作。非常感谢!
猜你喜欢
  • 2020-08-02
  • 2017-03-11
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 2018-10-26
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多