如何在d3.js中更改数据时强制重新计算元素属性?

时间:2013-12-02 08:45:50

标签: d3.js

我正在尝试研究D3.js是如何工作的,但我无法理解一些(可能)基本原则......我会很感激一些帮助。

根据我的理解,此代码段会创建rect SVG元素并设置其属性:

var nodes = d3.selectAll('circle.node')
    .data(mydata)
  .enter()
    .append('rect').class('attr', 'node');

// now set some attributes on these SVG elements:
nodes.attr('...', function(d) {
    return '...'; 
});

当数据稍后更改时,我的猜测是我只需要这样做:

d3.selectAll('circle.node')
    .data(mydata) // doesn't work as I would expect

但是,上面的代码段不能像我预期的那样工作。如果我想要更改属性,我仍然需要在选择上调用attr(),即使该属性被指定为数据的函数并且应该能够重新计算自身。更糟糕的是,如果我想强制重新计算,我需要指定相同的匿名函数。

为什么?是否有.updateMyAttributesFromData()函数我以某种方式错过了?像这样:

d3.selectAll('circle.node')
    .data(mydata)
    .updateMyAttributesFromData(); // not a real function

我错过了什么吗?

-

顺便说一下,为了避免“重复问题”标记:问题How to update elements when the underlying data changes with d3js有一个很有希望的标题,但不幸的是内容完全不同。 :)

1 个答案:

答案 0 :(得分:3)

您没有错过任何内容,这只是D3的工作方式 - 更新数据时,您的属性不会自动更新。也就是说,在分配新数据时,您确实必须再次运行相同的代码。这是一个设计决定,而不是错误。

然而,通过将执行所有这些操作的代码包装在一个需要执行此操作的函数中,可以使其更容易(并且更少冗余)数据。

function update(data) {
  var sel = d3.selectAll("foo").data(data);

  sel.enter().append("foo");

  // elements added in the enter selection merge into the update selection,
  // so this attribute is set for the elements that have just been added as well
  sel.attr("foo", "bar");

  sel.exit().remove();
}

不自动执行属性更新的一个原因(除了增加的实现复杂性)是渲染元素通常是数据密集型应用程序的瓶颈。如果这是自动发生的,即使您实际上不需要更新任何内容,也总会产生这种性能开销。此外,它对.exit()选择不会很好(即更新将要删除的元素的属性)。