D3JS选拔和课程

时间:2013-10-31 17:46:05

标签: d3.js

是否有一种简单的方法可以扩展以下代码,以便在div.someclass不存在时自动创建它?

d3.select("body").select("div.someclass").selectAll("p")
    .data([ 1, 2, 3 ])
    .enter()
        .append("p")
        .text(function (d, i) {
            return "index: " + i + ", value: " + d;
        });

我还处于学习D3JS的早期阶段。到目前为止,我对它的理解是“不是告诉D3如何做某事,而是告诉D3你想要什么”。所以我很惊讶地看到上面的代码需要在HTML中声明<div class="someclass"></div>

另一种方法是以编程方式插入div:

/** Append HTML placeholder programmatically **/
placeholder = d3.select("body").append("div").attr("class", "someclass");

/** Bind the data to the DOM **/
/** instead of telling D3 how to do something, tell D3 what you want: in the absence of <p>, this will return a virtual selection **/
placeholder.selectAll("p")
    .data([ 1, 2, 3 ])
    .enter()
        .append("p")
        .text(function (d, i) {
            return "index: " + i + ", value: " + d;
        });

有更短/更好的方式吗?

2 个答案:

答案 0 :(得分:10)

如果我理解正确,你问的是如何追加div.someClass IFF它不存在。这有一个D3模式,虽然它有点奇怪:

// create a selection for the container with a static 1-element array
var container = d3.select("body").selectAll("div.someclass")
    .data([0]); 

// now add it if it doesn't exist
container.enter().append('div').attr('class', 'someclass');

// now use it for the subselection
container.selectAll("p")
    .data([1, 2, 3]);

// etc

这里的奇怪部分是.data([0]) - 0是传统的,不是必需的;这可以是任何静态单元素数组。第一次调用它时,将创建一个新元素(除非先创建其他内容div.someclass)。第二次,元素已经存在,因此没有.enter()选择,并且不会再添加任何内容。

这是可重用组件中相当常见的模式,可以在更新时重复调用 - 有关示例,请参阅d3.svg.axis code

答案 1 :(得分:0)

你这样做的方式是正确的。通常,您以编程方式将类添加到以编程方式创建的节点。例如,您正在创建新的<p>元素,以便在需要时可以在那里添加类:

placeholder.selectAll("p")
    .data([ 1, 2, 3 ])
    .enter()
    .append("p")
        .attr("class", "myclass")   <-- add class here
        .text(function (d, i) {
            return "index: " + i + ", value: " + d;
        });

对于您不使用D3管理生命周期的元素,您还需要以其他方式管理这些元素的属性。这可以在初始HTML中进行硬编码,或者您可以完全按照原样添加特殊处理。

或者,还有一个名为selection.classed的API,当且仅当它们不存在时才会添加或删除类。如果你的元素可能包含很多类,而你只想在列表中切换一个(而不是selection.attr("class", "myclass"),这将会破坏整个属性,这可能很方便。