Network Graph - Cluster with Offset

by Rajesh Danabal

HTML

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Canvas Network Graph with Clusters</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
      body {
        margin: 0;
        overflow: hidden;
        font-family: Arial, sans-serif;
      }
      canvas {
        display: block;
      }
      .controls {
        position: fixed;
        top: 10px;
        left: 10px;
        background-color: rgba(255, 255, 255, 0.8);
        padding: 10px;
        border-radius: 5px;
      }
      label {
        display: block;
        margin: 5px 0;
      }
      input {
        margin-left: 5px;
        width: 60px;
      }
    </style>
  </head>
  <body>
    <div class="controls">
      <label for="offsetX">Cluster Offset X:</label>
      <input type="number" id="offsetX" value="40" step="1" min="0" />
      <label for="offsetY">Cluster Offset Y:</label>
      <input type="number" id="offsetY" value="60" step="1" min="0" />
    </div>

    <canvas id="networkCanvas"></canvas>

    <script>
      const canvas = document.getElementById("networkCanvas")
      const ctx = canvas.getContext("2d")

      canvas.width = window.innerWidth
      canvas.height = window.innerHeight

      const numNodes = 100
      const numClusters = 5
      const clusterCenters = []
      let hullOffsetX = 40 // Default X offset
      let hullOffsetY = 60 // Default Y offset

      // Generate cluster centers
      for (let i = 0; i < numClusters; i++) {
        clusterCenters.push({
          x: Math.random() * canvas.width,
          y: Math.random() * canvas.height,
        })
      }

      // Generate colors for clusters (hex format)
      const clusterColors = d3.schemeCategory10.slice(0, numClusters)

      // Convert hex to RGBA for transparent cluster background
      function hexToRgba(hex, alpha = 0.1) {
        hex = hex.replace(/^#/, "")
        if...