d3.js用于输入选择和更新选择的重复代码

Aar*_*hen 2 d3.js

我正在使用d3.js开发一些图表.我只是在写一些函数来在屏幕上绘制一些线条.但我发现自己编写了重复代码来设置属性以进入选择和更新选择.更糟糕的是,这是不可避免的.

检查以下代码.最初,我认为这很酷.每次更改输入数据时,我都可以调用此函数,图表将相应更新:如果有更多数据到来,将添加新行,如果仅更改数据,则将重新绘制现有行.

function drawLines(data){

    svg.selectAll('line')
        .data(data)
        .enter()
        .append('line')
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });;
}
Run Code Online (Sandbox Code Playgroud)

但我觉得它不起作用.append方法不会同时返回update + enter选择.我还在研究输入选择.所以我必须编写如下代码:

function drawLines(data){

    var updateSelection = svg.selectAll('line')
                            .data(data);

    var enterSelection = updateSelection
                            .enter()
                            .append('line');

    enterSelection
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });

    updateSelection
        .attr({
            x1: function(d){
                return d.x1;
            },
            y1: function(d){
                return d.y1;
            },
            x2: function(d){
                return d.x2;
            },
            y2: function(d){
                return d.y2
            }
        })
        .style({
            stroke: 'black',
            'stroke-width': 4
        });
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,我要复制attr,样式代码只是为了在输入选择和更新选择上做同样的操作.但是d3.js文档的enter方法部分说:

在追加或插入时,输入选择会合并到更新选择中.这种方法减少了输入和更新之间的代码重复.您可以在输入节点后将其应用于更新选择,而不是将运算符分别应用于输入和更新选择.在极少数情况下,您只想在更新节点上运行运算符,您可以在更新选择之前运行它们,然后再输入新节点.

现在我很困惑这意味着"输入选择合并到更新选择"和"减少输入和更新之间的代码重复".难道我做错了什么?据我了解,输入和更新之间的重复代码是不可避免的!

Lar*_*off 10

文档的含义是,一旦添加元素,它们将成为更新选择的一部分.也就是说,您在更新选择上设置的任何属性也将在您之前输入选择中添加的元素上设置.所以你只需要以下代码:

var updateSelection = svg.selectAll('line')
                        .data(data);

updateSelection.enter().append('line');

updateSelection
    .attr({
        x1: function(d){
            return d.x1;
        },
        y1: function(d){
            return d.y1;
        },
        x2: function(d){
            return d.x2;
        },
        y2: function(d){
            return d.y2
        }
    })
    .style({
        stroke: 'black',
        'stroke-width': 4
    });
Run Code Online (Sandbox Code Playgroud)

请注意,代码的顺序在这里很重要 - 您需要在设置更新选择的属性之前附加输入选择的元素.