Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3.js duplicate code for enter selection and update selection

Tags:

d3.js

I'm developing some chart using d3.js. I'm just writing some function to draw some lines on screen. But I found myself writing duplicate code for setting attributes to enter selection and update selection. And even more worse, it's inevitable.

check the below code. Initially, I think it's cool. Every time the input data is changed, I can just call this function, and the chart will just update accordingly: if there's more data coming, new lines will be added, if only data is changed, the existing lines will be redrew.

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
        });;
}

But I find it's not working. The append method doesn't return the update + enter selection together. I'm still working on the enter selection. So I have to write code like below:

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
        });
}

As you can see I'm wring duplicate attr, style code just to do same operation on enter selection and update selection. But the enter method section of d3.js documentation says:

The enter selection merges into the update selection when you append or insert. This approach reduces code duplication between enter and update. Rather than applying operators to both the enter and update selection separately, you can now apply them to the update selection after entering the nodes. In the rare case that you want to run operators only on the updating nodes, you can run them on the update selection before entering new nodes.

Now I'm confused about what it means "enter selection merges into the update selection" and "reduces code duplication between enter and update". Am I doing something wrong? As my understanding, the duplicate code between enter and update is inevitable!

like image 255
Aaron Shen Avatar asked Oct 23 '25 12:10

Aaron Shen


1 Answers

What the documentation means is that once you append elements, they will be part of the update selection. That is, any attributes you set on the update selection will also be set on the elements you have appended from the enter selection just before. So you only need the following code:

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
    });

Note that the order of the code is important here -- you need to append the elements of the enter selection before setting the attributes of the update selection.

like image 169
Lars Kotthoff Avatar answered Oct 26 '25 07:10

Lars Kotthoff