Public
Edited
Oct 29, 2024
Insert cell
Insert cell
{
const w = width;
const h = height*2;
const color = d3.scaleOrdinal(d3.schemeTableau10);
const svg = d3.create("svg").attr("viewBox", [0, 0, w, h]),
link = svg
.selectAll(".link")
.data(graph.links)
.join("line")
.classed("link", true),
node = svg
.selectAll(".node")
.data(graph.nodes)
.join("circle")
.attr("r", 5)
.style("fill", d => color(d.type))
.classed("node", true)
.classed("fixed", d => d.fx !== undefined);
let linkLabel = svg
.selectAll(".link-label")
.data(graph.links)
.join("text")
.text(d => d.type)
.classed('link-label', true)
let nodeLabel = svg
.selectAll(".node-label")
.data(graph.nodes)
.join("text")
.text(d => `${d.id} (${d.type})`)
.classed('node-label', true)

yield svg.node();

const simulation = d3
.forceSimulation()
.nodes(graph.nodes)
.force("charge", d3.forceManyBody().strength(-5))
.force("center", d3.forceCenter(w/2, h/2).strength(0.1))
.force("link", d3.forceLink(graph.links).distance(40))
.on("tick", tick);

const drag = d3
.drag()
.on("start", dragstart)
.on("drag", dragged);

nodeLabel.call(drag).on("click", click);

function tick() {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
nodeLabel
.attr("x", d => d.x)
.attr("y", d => d.y);
linkLabel
.attr("x", d => (d.source.x + d.target.x) / 2)
.attr("y", d => (d.source.y + d.target.y) / 2)
}

function click(event, d) {
delete d.fx;
delete d.fy;
// d3.select(this).classed("fixed", false);
simulation.alpha(1).restart();
}

function dragstart() {
// d3.select(this).classed("fixed", true);
}

function dragged(event, d) {
d.fx = clamp(event.x, 0, width);
d.fy = clamp(event.y, 0, height);
simulation.alpha(1).restart();
}
}
Insert cell
d3 = require("d3@6")
Insert cell
height = Math.min(500, width * 0.6)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more