Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
450 views
in Technique[技术] by (71.8m points)

d3.js - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...