Created
January 19, 2024 13:16
-
-
Save Damecek/7ffe05302abb345337ce86412d7956b2 to your computer and use it in GitHub Desktop.
Small html page used for visualizing dependency from happysoup.io
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Dependency Graph Visualization</title> | |
| <script src="https://d3js.org/d3.v5.min.js"></script> | |
| <style> | |
| body, html { | |
| margin: 0; | |
| padding: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .nodes circle { | |
| stroke: #fff; | |
| stroke-width: 1.5px; | |
| } | |
| .nodes text { | |
| font-size: 12px; | |
| font-family: sans-serif; | |
| display: none; | |
| } | |
| .links line { | |
| stroke: #999; | |
| stroke-opacity: 0.6; | |
| } | |
| #controls { | |
| position: absolute; | |
| top: 20px; | |
| left: 20px; | |
| z-index: 100; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="controls"> | |
| <input type="file" id="csvFileInput" accept=".csv" onchange="handleFileSelect(event)"> | |
| <button id="toggleLabels">Toggle Labels</button> | |
| </div> | |
| <svg></svg> | |
| <script> | |
| var showLabels = false; | |
| function handleFileSelect(evt) { | |
| var file = evt.target.files[0]; | |
| var reader = new FileReader(); | |
| reader.readAsText(file); | |
| reader.onload = function(event) { | |
| var csvData = event.target.result; | |
| var parsedCSV = d3.csvParse(csvData); | |
| document.getElementById('csvFileInput').style.display = 'none'; | |
| renderGraph(parsedCSV); | |
| }; | |
| } | |
| function renderGraph(data) { | |
| var color = d3.scaleOrdinal(d3.schemeCategory10); | |
| var width = window.innerWidth; | |
| var height = window.innerHeight; | |
| var svg = d3.select("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .call(d3.zoom().on("zoom", function () { | |
| svg.attr("transform", d3.event.transform) | |
| })) | |
| .append("g"); | |
| var g = svg.append("g") | |
| .call(d3.zoom().on("zoom", function () { | |
| g.attr("transform", d3.event.transform) | |
| })); | |
| var nodes = []; | |
| var links = []; | |
| data.forEach(function(row) { | |
| nodes.push({id: row.Name, type: row['Metadata Type']}); | |
| if (row['Used by']) { | |
| links.push({source: row.Name, target: row['Used by']}); | |
| } | |
| }); | |
| nodes = Array.from(new Set(nodes.map(JSON.stringify)), JSON.parse); | |
| var simulation = d3.forceSimulation(nodes) | |
| .force("link", d3.forceLink(links).id(function(d) { return d.id; })) | |
| .force("charge", d3.forceManyBody()) | |
| .force("center", d3.forceCenter(width / 2, height / 2)); | |
| var link = svg.append("g") | |
| .attr("class", "links") | |
| .selectAll("line") | |
| .data(links) | |
| .enter().append("line"); | |
| var node = svg.append("g") | |
| .attr("class", "nodes") | |
| .selectAll("g") | |
| .data(nodes) | |
| .enter().append("g") | |
| .call(d3.drag() | |
| .on("start", dragstarted) | |
| .on("drag", dragged) | |
| .on("end", dragended)); | |
| node.append("circle") | |
| .attr("r", 5) | |
| .style("fill", function(d) { return color(d.type); }); | |
| var labels = node.append("text") | |
| .text(function(d) { return d.id; }) | |
| .attr('x', 6) | |
| .attr('y', 3) | |
| .style("display", "none"); | |
| // Bring labels to front | |
| node.each(function() { | |
| d3.select(this).select("text").raise(); | |
| }); | |
| // Add hover event listeners | |
| node.on("mouseover", function() { | |
| d3.select(this).select("text").style("display", "block"); | |
| }) | |
| .on("mouseout", function() { | |
| d3.select(this).select("text").style("display", "none"); | |
| }); | |
| var legend = svg.append("g") | |
| .attr("class", "legend") | |
| .selectAll("g") | |
| .data(color.domain()) | |
| .enter().append("g") | |
| .attr("transform", function(d, i) { return "translate(" + (width - 120) + "," + (i * 20 + 20) + ")"; }); | |
| legend.append("rect") | |
| .attr("width", 18) | |
| .attr("height", 18) | |
| .style("fill", color); | |
| legend.append("text") | |
| .attr("x", 24) | |
| .attr("y", 9) | |
| .attr("dy", ".35em") | |
| .text(function(d) { return d; }); | |
| // Update legend position | |
| legend.attr("transform", function(d, i) { | |
| return "translate(" + (width - 150) + "," + (20 + i * 20) + ")"; | |
| }); | |
| simulation.on("tick", function() { | |
| link | |
| .attr("x1", function(d) { return d.source.x; }) | |
| .attr("y1", function(d) { return d.source.y; }) | |
| .attr("x2", function(d) { return d.target.x; }) | |
| .attr("y2", function(d) { return d.target.y; }); | |
| node | |
| .attr("transform", function(d) { | |
| return "translate(" + d.x + "," + d.y + ")"; | |
| }); | |
| }); | |
| document.getElementById("toggleLabels").addEventListener("click", function() { | |
| showLabels = !showLabels; | |
| labels.style("display", showLabels ? "block" : "none"); | |
| }); | |
| function dragstarted(d) { | |
| if (!d3.event.active) simulation.alphaTarget(0.3).restart(); | |
| d.fx = d.x; | |
| d.fy = d.y; | |
| } | |
| function dragged(d) { | |
| d.fx = d3.event.x; | |
| d.fy = d3.event.y; | |
| } | |
| function dragended(d) { | |
| if (!d3.event.active) simulation.alphaTarget(0); | |
| d.fx = null; | |
| d.fy = null; | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment