import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm" import { forceSimulation, forceLink, forceCollide, } from "https://cdn.jsdelivr.net/npm/d3@7/+esm" const data = { nodes: [ { id: "A", group: 1 }, { id: "B", group: 1 }, { id: "C", group: 1 }, { id: "D", group: 1 }, { id: "E", group: 1 }, { id: "F", group: 1 }, { id: "G", group: 1 }, { id: "H", group: 1 }, { id: "I", group: 1 }, { id: "J", group: 1 }, { id: "K", group: 1 }, { id: "L", group: 1 }, { id: "M", group: 1 }, { id: "N", group: 1 }, { id: "O", group: 1 }, { id: "P", group: 1 }, { id: "Q", group: 1 }, { id: "R", group: 1 }, { id: "S", group: 1 }, { id: "T", group: 1 }, { id: "U", group: 1 }, { id: "V", group: 1 }, { id: "W", group: 1 }, { id: "X", group: 1 }, { id: "Y", group: 1 }, { id: "Z", group: 1 }, ], links: [ { source: "A", target: "B", value: 1 }, { source: "A", target: "C", value: 1 }, { source: "A", target: "D", value: 1 }, { source: "A", target: "E", value: 1 }, { source: "A", target: "F", value: 1 }, { source: "A", target: "G", value: 1 }, { source: "A", target: "H", value: 1 }, { source: "A", target: "I", value: 1 }, { source: "A", target: "J", value: 1 }, { source: "A", target: "K", value: 1 }, { source: "A", target: "L", value: 1 }, { source: "A", target: "M", value: 1 }, { source: "A", target: "N", value: 1 }, { source: "A", target: "O", value: 1 }, { source: "A", target: "P", value: 1 }, { source: "A", target: "Q", value: 1 }, { source: "A", target: "R", value: 1 }, { source: "A", target: "S", value: 1 }, { source: "A", target: "T", value: 1 }, { source: "A", target: "U", value: 1 }, { source: "A", target: "V", value: 1 }, { source: "A", target: "W", value: 1 }, { source: "A", target: "X", value: 1 }, { source: "A", target: "Y", value: 1 }, { source: "A", target: "Z", value: 1 }, ], } const width = window.innerWidth const height = window.innerHeight const svg = d3 .select("body") .append("svg") .attr("width", width) .attr("height", height) const simulation = forceSimulation(data.nodes) .force( "link", forceLink(data.links).id((d) => d.id) ) .force("collide", forceCollide(30)) const link = svg .selectAll("line") .data(data.links) .enter() .append("line") .attr("stroke", "black") .attr("stroke-width", 1) const node = svg .selectAll("circle") .data(data.nodes) .enter() .append("circle") .attr("r", 10) .attr("fill", "red") .call( d3.drag().on("start", dragStarted).on("drag", dragged).on("end", dragEnded) ) node.append("title").text((d) => d.id) const text = svg .selectAll("text") .data(data.nodes) .enter() .append("text") .attr("x", (d) => d.x) .attr("y", (d) => d.y + 20) .text((d) => d.id) .attr("text-anchor", "middle") .attr("fill", "black") simulation.on("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) text.attr("x", (d) => d.x).attr("y", (d) => d.y + 20) }) node.on("click", function (event, d) { d.fx = null d.fy = null }) function dragStarted(event, d) { if (!event.active) simulation.alphaTarget(0.3).restart() d.fx = d.x d.fy = d.y } function dragged(event, d) { d.fx = event.x d.fy = event.y } function dragEnded(event, d) { if (!event.active) simulation.alphaTarget(0) if (!d3.event.active) { d.fx = d.x d.fy = d.y } }