import './style.css'; import Graph from "graphology"; import Sigma from "sigma"; import forceAtlas2 from "graphology-layout-forceatlas2"; // --- Génération de données de base --- const graph = new Graph(); const N = 30; const colors = ["#ec635e", "#61afef", "#2c3029ff", "#e5c07b"]; for (let i = 0; i < N; i++) { const sex = Math.random() < 0.5 ? "F" : "M"; const education = Math.floor(Math.random() * 4); const color = colors[education]; graph.addNode(`n${i}`, { x: Math.random(), y: Math.random(), label: `${sex} ${i}`, sex, education, size: 6 + education, color, }); } let total = N * 1.5 // --- Calcul du layout ForceAtlas2 --- /* const positions = forceAtlas2(graph, { iterations: 50 }); // --- Application des positions calculées --- for (const [node, pos] of Object.entries(positions)) { graph.setNodeAttribute(node, "x", pos.x); graph.setNodeAttribute(node, "y", pos.y); } */ // --- Rendu Sigma --- const container = document.getElementById("app"); const renderer = new Sigma(graph, container, { renderLabels: true }); // --- Fonctions dynamiques --- function addLink() { const a = `n${Math.floor(Math.random() * N)}`; const b = `n${Math.floor(Math.random() * N)}`; if (a !== b && !graph.hasEdge(a, b)) { graph.addEdge(a, b, { color: "#da1515ff", size: 1 }); } if (total-- > 0) setTimeout(() => addLink(), 1000); else running = false; } function removeLink(source, target) { if (graph.hasEdge(source, target)) { graph.dropEdge(source, target); renderer.refresh(); } } // --- Exemple d’évolution dynamique --- setTimeout(() => addLink(), 250); setTimeout(() => removeLink("n1", "n2"), 8000); // --- Animation du layout --- // On crée une "simulation" ForceAtlas2 en incrémentant les positions à chaque frame. let running = true; function stepLayout() { if (!running) return; // Effectue une itération de ForceAtlas2 (ne recrée pas tout) forceAtlas2.assign(graph, { iterations: 1, settings: { gravity: 0.1, scalingRatio: 10 } }); // Sigma détecte les changements automatiquement → inutile de refresh manuellement requestAnimationFrame(stepLayout); } // Lancement stepLayout(); /* const layout = new ForceAtlas2Layout(graph, { settings: { gravity: 0.1, slowDown: 10, linLogMode: false, outboundAttractionDistribution: false, adjustSizes: true, }, }); // --- Animation : on démarre le layout --- layout.start(); // --- Optionnel : arrêt automatique après quelques secondes --- setTimeout(() => { layout.stop(); console.log("Layout stabilisé"); }, 5000); // --- Animation continue du rendu --- function animate() { // On redessine continuellement le graphe tant que le layout tourne renderer.refresh(); requestAnimationFrame(animate); } animate(); */ //import typescriptLogo from './typescript.svg' //import viteLogo from '/vite.svg' //import { setupCounter } from './counter.ts' /* document.querySelector('#app')!.innerHTML = `

Vite + TypeScript

Click on the Vite and TypeScript logos to learn more

` setupCounter(document.querySelector('#counter')!) */