简体   繁体   中英

Setting up links in d3 force layout

I am trying to set up a d3 force visualization with nodes and links. I have my nodes displaying properly but am having some trouble with links. Could someone take a look at my json file and then my code and guide me through the process of getting the links to display?

Here's the json data (sources and targets for links are at the bottom):

https://api.myjson.com/bins/4t8na

And here's the code for the visualization:

  <script type= "text/javascript"> var w = 1000, h = 650; var svg = d3.select("body").append("svg") .attr("height", 0) .attr("width", 0) .style("border", "1px solid black"); var data; // a global var force = d3.layout.force() .size([w, h]) .linkDistance([150]) .charge([-1050]) .gravity(0.5) .on("tick", tick); var svg = d3.select("body").append("svg") .attr("width", w) .attr("height", h); var circles = svg.selectAll(".node"); d3.json("https://api.myjson.com/bins/1rnhq", function(error, json) { if (error) return console.warn(error); data = json; var nodes = data; console.log(data); force.nodes(data)//.links() .start(); // Update nodes. circles = circles.data(data); circles.exit().remove(); var nodeEnter = circles.enter().append("g") .attr("class", "node") .style("fill", "#000") .style("opacity", 0.75) .on("mouseover", mouseover) .on("mouseout", mouseout) .on("click", click) .call(force.drag); nodeEnter.append("circle") .attr("r", function(d) { return d.sector == "Academia" ? 1:5 }); nodeEnter.attr("cursor", "pointer"); //Update links var links = svg.selectAll(".link") .data(data.links) .enter().append("line") .attr("class", "link") .style("stroke-width", "1px"); links.exit().remove(); function mouseover() { d3.select(this).select("circle").transition() .duration(250) .attr('r', 10); } function mouseout() { d3.select(this).select("circle").transition() .duration(250) .attr('r', 5); } nodeEnter.append("text") .attr("text-anchor", "middle") .style("font-size", ".75em") .attr("dy", "-0.85em").text(function (d) { return d.name }); var tooltip = svg.append("rect") .attr("x", 1000) .attr("y", 0) .attr("width", 900) .attr("height", 700) .attr("opacity", 0.85); function click() { d3.select(tooltip).transition() .duration(450) .attr("x", 650) }; }); function tick() { links.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); circles.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); }; // create svg nodes for each json object: "sector" // create svg nodes for each json object: "name" // load links.json // create svg links from links json file // style links // sort json objects by projects // get google map: coastal virginia // sort json objects: "name" by geography // get googe map US </script> 

I believe the problem is that data.links does not exist, what you have is data[#].links . So when you do .data(data.links) on your var links = ... , you are passing an undefined attribute there.

Try this:

var links = svg.selectAll(".link")
            .data(data)
            // ...

The main problem is inside your JSON links You have values like this:

{"source":52,"target":28},{"source":52,"target":29},{"source":52,"target":30},{"source":52,"target":31}

But there is no Node with index 52 thus everything was breaking on load. However you code has lot of other errors like

circles.exit().remove();//this is incorrect coz circles in your case is not a selection

And many more :)

Working code here

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM