Ian
Ian

Reputation: 34489

Why is the first Link item being skipped?

I've got a fairly simple visualization I'm trying to put together, but having a slight issue with the processing.

If I use the following snippet then everything works as expected:

var lines = svg.selectAll("line")
                        .data(data.links)
                        .enter()
                        .append("svg:line")
                            .attr("x1", function(d) { return findNode(data.nodes, d.source).x;})
                            .attr("y1", function(d) { return findNode(data.nodes, d.source).y;})
                            .attr("x2", function(d) { return findNode(data.nodes, d.target).x;})
                            .attr("y2", function(d) { return findNode(data.nodes, d.target).y;})
                            .style("stroke", "#838383")
                            .style("stroke-width", 1)
                            .style("marker-end", "url(#end-arrow)");

If I switch this however to use a slightly different one, using paths:

var paths = svg.selectAll("path")
                        .data(data.links)
                        .enter()
                        .append("svg:path")
                            .attr("d", function(d) { 
                                debugger;
                                var src = findNode(data.nodes, d.source);
                                var tgt = findNode(data.nodes, d.target);
                                var xi = d3.interpolateNumber(src.x, tgt.x);
                                var curvature = 0.8;

                                return "M" + src.x + "," + src.y
                                     + "C" + xi(curvature) + "," + src.y
                                     + " " + xi(1 - curvature) + "," + tgt.y
                                     + " " + tgt.x + "," + tgt.y;
                            })
                            .style("stroke", "#838383")
                            .attr("fill", "none");

Then for some reason the first 'link' is missing. Can anyone suggest why this might be? There's a JSFiddle here. The effect that expected is missing, is that I don't have nice rounded lines like I want.

Upvotes: 9

Views: 1164

Answers (1)

Lars Kotthoff
Lars Kotthoff

Reputation: 109232

The problem is that D3 matches your selection .selectAll("path") to your data by index by default and there is already a path in the SVG (in the defs). That is, the first data element matches the first path in the SVG, which is already there. Therefore, it is not in the .enter() selection.

The way to fix this is to specify a function in the optional second argument of .data() to tell D3 how to match elements, e.g.

.data(data.links, function(d, i) { return d + i; })

Upvotes: 13

Related Questions