Visualize 3D graph in 2D
by Rajesh Danabal
HTML
<canvas id="canvas"></canvas>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const numNodes = 80;
const radius = 250;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
// Generate nodes with simulated 3D depth
const nodes = d3.range(numNodes).map((i) => {
const angle = (i / numNodes) * 2 * Math.PI;
const depth = Math.random(); // Simulated Z-depth (0: far, 1: near)
return {
id: i,
x: centerX + radius * Math.cos(angle) * (0.8 + 0.2 * depth),
y: centerY + radius * Math.sin(angle) * (0.8 + 0.2 * depth),
size: 3 + 6 * depth, // Larger nodes appear closer
opacity: 0.3 + 0.7 * depth, // Fainter nodes appear farther
depth
};
});
// Generate random links with fading effect
const links = [];
for (let i = 0; i < numNodes; i++) {
for (let j = i + 1; j < numNodes; j++) {
if (Math.random() < 0.1) { // 10% chance of connection
links.push({ source: nodes[i], target: nodes[j] });
}
}
}
// Draw function
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Sort nodes by depth to ensure proper layering
nodes.sort((a, b) => a.depth - b.depth);
// Draw edges with depth-based opacity
links.forEach((link) => {
ctx.strokeStyle = `rgba(100, 100, 100, ${0.2 + 0.4 * (link.source.depth + link.target.depth) / 2})`;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(link.source.x, link.source.y);
ctx.lineTo(link.target.x, link.target.y);
ctx.stroke();
});
// Draw nodes with depth-based size & opacity
nodes.forEach((node) => {
ctx.beginPath();
ctx.arc(node.x, node.y, node.size, 0, 2 * Math.PI);
ctx.fillStyle = `rgba(30, 144, 255, ${node.opacity})`;
ctx.fill();
});
...