使用d3.js的selectAll()传播数据

时间:2014-04-05 05:44:59

标签: javascript d3.js

d3.js中是否有内置方法,这样我就可以使用select(selector)传播与selectAll(selector)类似的数据?

如果没有这种直接方式,请提出其他任何有关如何改善数据传播的提示。

请阅读我的例子的评论。这是它的bl.ocks.org

示例:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.chart div {
    margin: 3px;
    padding: 1px;
}
.chart > div {
    background-color: red;
}
.chart > div > div {
    background-color: steelblue;
    color: white;
}
</style>
<div class="chart"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
function draw(data) {
    var divs = d3
        .select(".chart")
        .selectAll(".parent")
        .data(data);
    var enter = divs
        .enter()
        .append('div')
        .attr('class', 'parent');
    enter
        .append("div")
        .attr('class', 'first');
    enter
        .append("div")
        .attr('class', 'second');

    // Feel free to change the method if you want to test
    var method = 3;
    switch(method) {
    case 1:
        // This works, obviously:
        divs
            .select('.first')
            .text(function(d) { return d.i; });
        divs
            .select('.second')
            .text(function(d) { return d.i; });
        break;

    case 2:
        // This works also, as I create new propagated data:
        divs
            .selectAll('div')
            .data(function(d) {
                var padded = [];
                for(var i = 0; i < this.length; ++i) {
                    padded.unshift(d);
                }
                return padded;
            })
            .text(function(d) { return d.i; });
        break;

    case 3:
        // I could do also this:
        divs
            .selectAll('div')
            .call(padData)
            .text(function(d) { return d.i; });
        break;

    default:
        // I'd like to do something similar, built-in into d3.js, which selects all the divs and sets their value without manual the propagation and padding:
        // divs.selectAll('div').text(function(d) { return d.i; });
        break;
    }
}

function padData(divs) {
    return divs.data(function(d) {
        var padded = [];
        for(var i = 0; i < this.length; ++i) {
            padded.push(d);
        }
        return padded;
    });
}

var d = [];
for (var i = 0; i < 5; ++i) {
    d.unshift({i:i});
}
draw(d);

window.setInterval(function() {
    var r = Math.random()*100;
    d.unshift({i:r});
    d.pop();
    draw(d);
}, 2000);
</script>

1 个答案:

答案 0 :(得分:3)

我并不完全清楚你要做什么,但.select()是唯一将数据传播到子元素的运算符。在选择中使用.selectAll()通常意味着您想要执行nested selections tutorial之类的操作,在这种情况下,您需要再次使用显式.data()来告诉D3嵌套数据的哪些部分使用

在许多情况下,您可以通过修改数据而不是传播数据来实现您想要的效果。例如,如果您想要一定数量的重复元素,您也可以在数据中重复这些元素。 D3背后的想法(顾名思义)可视化(几乎)完全由数据驱动。也就是说,如果你有复杂的数据继承和传播,这应该反映在数据中而不仅仅是代码中。