为什么我的 d3.js selectAll + filter 没有过滤?

Why is my d3.js selectAll + filter not filtering?

我正在尝试为每一天创建一个父 g 标签,该标签将包含一个子 g 标签。代码的第一个项目部分正确生成父项:

var content = d3.select(".content").attr("height", 1000).attr("width", 1000);

//create day groups
var days = content.selectAll("g").filter(".day")
        .data([0,1,2,3,4,5,6,7,8,9])
        .enter().append("g")
        .attr("class", "day");

当我尝试为每个标签添加子 g 标签时,它不起作用:

// create the day headers
var day_labels = days.selectAll("g").filter(".day_label")    
        .data(function (d) {
            return d;
        })
        .enter().append("g")
        .attr("class", "day_label");

我的语法有问题吗?

问题出在您的数据绑定中。 selection.data() 期望绑定一个数组,这在您创建日期组的第一部分中运行良好。但是请记住,d3.selectAll() 会将它找到的元素分组,将数组的每个项目绑定到相应的组。第二部分中的 selection.selectAll() 将保留此分组并对每个组之前绑定的数据进行操作。因此,使用身份函数将数据绑定到子节点将 return 数组的项目绑定到相应的日期节点。例如,对于第一天标签,这将是 return 数组的第一项,即 0。但是,要使 selection.data() 处理子选择,这应该是一个数组。

检查 api 对 further details 的参考和示例:

For example, you may bind a two-dimensional array to an initial selection, and then bind the contained inner arrays to each subselection. The values function in this case is the identity function: it is invoked for each group of child elements, being passed the data bound to the parent element, and returns this array of data.

要使其正常工作,您可以:

  1. 绑定一个二维数组,你的情况有点笨拙

    var days = content.selectAll("g.day")
            .data([[0],[1],[2],[3],[4],[5],[6],[7],[8],[9]])
            .enter()
                .append("g")
                    .attr("class", "day");
    

    子部分保持原样。

  2. 父子结合创建

    var day_labels = content.selectAll("g.day")
                        .data([0,1,2,3,4,5,6,7,8,9])
                        .enter()
                            .append("g")
                                .attr("class", "day")
                            .append("g")
                                .attr("class", "day_label");
    

您的选择主要取决于您要对数据绑定执行的操作。

顺便问一下,您看过 Mike Bostock 关于 "How Selections Work" 的文章吗?绝对值得花时间阅读。