D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
john-guerra
Full window
Github gist
D3 Force Simulation
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <style> svg text { font-family: sans-serif; font-size: 24pt; text-anchor: middle; } </style> </head> <body> <h1>Force Directed layout</h1> <svg width=800 height=400 id="network"></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> // Copy drag from: https://bl.ocks.org/mbostock/4062045 let svg = d3.select("#network"), width = +svg.attr("width"), height = + svg.attr("height"), N = 100, r = d3.scaleSqrt() .domain([0, 50]) .range([1, 15]), x = d3.scaleBand() .domain(["M", "F"]) .range([50, width-50]), c = d3.scaleOrdinal() .domain(["M", "F"]) .range(["steelblue", "firebrick"]), y = d3.scaleLinear() .domain([20, 50]) .range([height, 0]), g = svg.append("g") .attr("class", "graph"), tooltip = svg.append("text"); let nodes = [ {name:"John", age:23, gender:"M"}, {name:"Edwin", age:25, gender:"M"}, {name:"Santi", age:25, gender:"M"}, {name:"Eliza", age:22, gender:"F"}, {name:"Magda", age:32, gender:"F"}, {name:"Vicente", age:43, gender:"M"}, {name:"Sonia", age:44, gender:"F"} ] let links = [ {source:"John", target:"Vicente", weigth:3}, {source:"Edwin", target:"Vicente"}, {source:"Santi", target:"Edwin"}, {source:"Eliza", target:"Vicente"}, {source:"Magda", target:"Vicente"}, {source:"John", target:"Sonia"}, {source:"Edwin", target:"Sonia"}, {source:"Eliza", target:"Sonia"}, ] console.log(width, height); let simulation = d3.forceSimulation(nodes) .force("x", d3.forceX((d) => x(d.gender)) .strength(0.3)) .force("y", d3.forceY((d) => y(d.age)) .strength(0.5)) // .force("charge", d3.forceManyBody().strength(-50)) .force("collide", d3.forceCollide(d => r(d.age) + 1)) .force("link", d3.forceLink(links) .id((d) => d.name) .distance(10).strength(0.1)) .on("tick", ticked); console.log("nodes", nodes); console.log("links", links); let sellinks = g.selectAll(".link") .data(links) .enter() .append("line") .attr("class", "link") .style("stroke", "#aaa") .style("stroke-width", "10px") .style("opacity", 0.9) let selnodes = g.selectAll(".node") .data(nodes) .enter() .append("circle") .attr("class", "node") .style("fill", d => c(d.gender)) .attr("r", d => r(d.age)) .on("mouseover", (d) => { tooltip.text(d.name) .transition() .duration(1000) .attr("x", d.x) .attr("y", d.y - 20); console.log("clicked!", d); }) .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); selnodes.append("title") .text(d => d.name); function ticked() { sellinks.attr("x1", (l) => l.source.x) .attr("y1", (l) => l.source.y) .attr("x2", (l) => l.target.x) .attr("y2", (l) => l.target.y); selnodes.attr("cx", (d) => d.x) .attr("cy", (d) => d.y); }// ticked function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } </script> </body>
https://d3js.org/d3.v4.min.js