Skip to content

Instantly share code, notes, and snippets.

@john-guerra
Last active November 15, 2018 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save john-guerra/2b66626b2338ced4718b1bf3f7283e49 to your computer and use it in GitHub Desktop.
Save john-guerra/2b66626b2338ced4718b1bf3f7283e49 to your computer and use it in GitHub Desktop.
D3 Force Simulation
license: mit
<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment