d3-network-diagram/plot.js

148 lines
3.6 KiB
JavaScript

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
}
}