JSFiddle - React, Tailwind, and code Playground
by novillo
HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Grafo interactivo</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<svg></svg>
</body>
</html>
CSS
body {
margin: 0;
background: #0f172a;
font-family: Arial, sans-serif;
overflow: hidden;
}
svg {
display: block;
width: 100vw;
height: 100vh;
}
.link {
stroke: rgba(255,255,255,0.25);
stroke-width: 2;
}
.node {
fill: #ff8300;
stroke: #fff;
stroke-width: 2;
cursor: grab;
transition: r 0.15s ease, fill 0.15s ease;
}
.node.dragging {
fill: #ffd166;
cursor: grabbing;
}
.label {
fill: white;
font-size: 12px;
text-anchor: middle;
pointer-events: none;
}
JavaScript
const width = window.innerWidth;
const height = window.innerHeight;
const nodes = [
{ id: "A" },
{ id: "B" },
{ id: "C" },
{ id: "D" },
{ id: "E" },
{ id: "F" }
];
const links = [
{ source: "A", target: "B" },
{ source: "A", target: "C" },
{ source: "B", target: "D" },
{ source: "C", target: "D" },
{ source: "C", target: "E" },
{ source: "D", target: "F" }
];
const svg = d3.select("svg")
.attr("viewBox", [0, 0, width, height]);
const link = svg.append("g")
.selectAll("line")
.data(links)
.join("line")
.attr("class", "link");
const node = svg.append("g")
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("class", "node")
.attr("r", 18);
const label = svg.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("class", "label")
.text(d => d.id);
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(120).strength(0.8))
.force("charge", d3.forceManyBody().strength(-450))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collision", d3.forceCollide().radius(35));
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);
label
.attr("x", d => d.x)
.attr("y", d => d.y + 4);
});
const drag = d3.drag()
.on("start", (event, d) => {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
d3.select(event.sourceEvent.target)
.classed("dragging", true)
.transition()
...