<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>3D Force-Directed Graph</title> <script src="https://d3js.org/d3.v7.min.js"></script> <style> body { margin: 0; overflow: hidden; } #graph-container { width: 100%; height: 100vh; } </style> </head> <body> <div id="graph-container"></div> <script> // Fetch the graph data from the Flask server fetch('/data') .then(response => response.json()) .then(data => { const nodes = data.nodes.map(node => ({ ...node, x: Math.random() * 1000 - 500, y: Math.random() * 1000 - 500, z: Math.random() * 1000 - 500 })); const links = data.edges; // Create the force-directed graph using D3.js const container = document.getElementById('graph-container'); const width = container.clientWidth; const height = container.clientHeight; const simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(links).id(d => d.id)) .force("charge", d3.forceManyBody().strength(-50)) .force("x", d3.forceX(width / 2)) .force("y", d3.forceY(height / 2)); const svg = d3.select(container) .append('svg') .attr('width', width) .attr('height', height); const link = svg.append('g') .attr('class', 'links') .selectAll('line') .data(links) .enter().append('line') .style("stroke-width", function(d) { return Math.sqrt(d.value); }); const node = svg.append('g') .attr('class', 'nodes') .selectAll('circle') .data(nodes) .enter().append('circle') .attr('r', 5) .attr('fill', '#69b3a2') .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); node.append('title') .text(d => d.id); simulation.on("tick", () => { link .attr("x1", d => d.source.x) .attr("y1", d => d.source.y) .attr("z1", d => d.source.z) .attr("x2", d => d.target.x) .attr("y2", d => d.target.y) .attr("z2", d => d.target.z); node .attr("cx", d => d.x) .attr("cy", d => d.y) .attr("cz", d => d.z); }); function dragstarted(event, d) { if (!event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; d.fz = d.z; } function dragged(event, d) { d.fx = event.x; d.fy = event.y; d.fz = event.z; } function dragended(event, d) { if (!event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; d.fz = null; } }); </script> </body> </html>