Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the first Link item being skipped?

Tags:

d3.js

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.

like image 209
Ian Avatar asked May 14 '13 13:05

Ian


1 Answers

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; })
like image 85
Lars Kotthoff Avatar answered Dec 12 '22 08:12

Lars Kotthoff