JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"></script>
<div id="controls-panel">
  <label for="speed-slider">Speed (ms): <span id="speed-label">100</span></label>
  <input type="range" id="speed-slider" min="5" max="500" value="200" step="10" />
  <br />
  <label for="people-input">People: </label>
  <!-- Add a "Confirm" button for the people input -->
<input id="people-input" type="number" value="30" min="1" max="200">
<button id="confirm-button">Confirm</button>

  <br />
  <button id="reset-button">Reset</button>
</div>

CSS

body { margin: 0; }
      canvas { display: block; }
      
       body {
        margin: 0;
      }
      #controls-panel {
        position: absolute;
        top: 10px;
        left: 10px;
        z-index: 1;
        background-color: white;
        padding: 15px;
        border-radius: 5px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
      }
      #controls-panel label,
      #controls-panel input,
      #controls-panel button {
        display: inline-block;
        vertical-align: middle;
        margin: 0 5px;
      }

JavaScript

const scene = new THREE.Scene();

// Add a light source
const light = new THREE.PointLight(0xffffff, 1, 100);
light.position.set(0, 0, 20);
scene.add(light);

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

let nodeCount = 30;
const radius = 15;
const circleGeometry = new THREE.CircleGeometry(0.5, 32);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xffa500, opacity: 1, transparent: true });

const nodes = [];
let currentNodeIndex = 0;
let currentConnectionIndex = 1;
let connectionCount = 0;
let matchLikelihood = 0;


function initializeNodes() {
  for (let i = 0; i < nodeCount; i++) {
    const circleMaterial = new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff });
    const circle = new THREE.Mesh(circleGeometry, circleMaterial);
    const angle = (i / nodeCount) * 2 * Math.PI;
    circle.position.set(radius * Math.cos(angle), radius * Math.sin(angle), 0);
    scene.add(circle);
    nodes.push(circle);
  }

  animate();
}


let previousLines = [];


// Add this function to reduce color saturation
function reduceSaturation(material, amount) {
  const color = material.color;
  const hsl = color.getHSL({ h: 0, s: 0, l: 0 });
  hsl.s -= amount;
  color.setHSL(hsl.h, Math.max(hsl.s, 0), hsl.l);
}

function connectNodes(nodeA, nodeB) {
  if (previousLines.length > 0) {
    // Change the color of all other lines to white
    previousLines.forEach((line, index) => {
      line.material.color.set(0xffffff);

      // Reduce the opacity of all previous lines by 5% (except the current line)
      if (index !== previousLines.length - 1) {
        line.material.opacity = Math.max(line.material.opacity * 0.95, 0.5);
      }
    });

    // Remove the thickness from the previous line
    const lastLine = previousLines[previousLines.length - 1];
   ...