// graph.js document.addEventListener('DOMContentLoaded', function() { const data = { nodes: [ { id: "Force", label: "Force" }, { id: "Mass", label: "Mass" }, { id: "Acceleration", label: "Acceleration" }, { id: "Gravity", label: "Gravity" }, { id: "Friction", label: "Friction" }, { id: "Motion", label: "Motion" } ], links: [ { source: "Force", target: "Mass", relationship: "is_applied_on" }, { source: "Force", target: "Acceleration", relationship: "causes" }, { source: "Gravity", target: "Mass", relationship: "acts_on" }, { source: "Friction", target: "Motion", relationship: "opposes" }, { source: "Force", target: "Friction", relationship: "overcomes" } ] }; const width = 800; const height = 600; const svg = d3.select("#graph").append("svg") .attr("width", width) .attr("height", height); const simulation = d3.forceSimulation(data.nodes) .force("link", d3.forceLink(data.links).id(d => d.id).distance(200)) .force("charge", d3.forceManyBody().strength(-500)) .force("center", d3.forceCenter(width / 2, height / 2)); const link = svg.append("g") .attr("stroke", "#999") .attr("stroke-opacity", 0.6) .selectAll("line") .data(data.links) .enter().append("line") .attr("stroke-width", d => Math.sqrt(d.value)); const node = svg.append("g") .attr("stroke", "#fff") .attr("stroke-width", 1.5) .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); // Add labels const labels = svg.append("g") .selectAll("text") .data(data.nodes) .enter().append("text") .attr("x", d => d.x) .attr("y", d => d.y) .attr("dy", -3) .attr("text-anchor", "middle") .text(d => d.label); 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); labels .attr("x", d => d.x) .attr("y", d => d.y); }); 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); d.fx = null; d.fy = null; } });