<div id="sigma-container"></div>
import { bindWebGLLayer, createContoursProgram } from "@sigma/layer-webgl";
import Graph from "graphology";
import louvain from "graphology-communities-louvain";
import Sigma, { DEFAULT_DEPTH_LAYERS } from "sigma";
import { registerControls } from "../_controls";
import data from "../_data/data.json";
const COMMUNITY_COLORS = [
const graph = new Graph();
louvain.assign(graph, { nodeCommunityAttribute: "community" });
const communities = new Set<string>();
graph.forEachNode((_, attrs) => communities.add(attrs.community));
const communitiesArray = Array.from(communities);
// Assign colors per community
const palette: Record<string, string> = {};
communitiesArray.forEach((c, i) => (palette[c] = COMMUNITY_COLORS[i % COMMUNITY_COLORS.length]));
graph.forEachNode((node, attrs) => graph.setNodeAttribute(node, "color", palette[attrs.community]));
// Declare one depth layer per community
const communityDepths = communitiesArray.map((c) => `community-${c}`);
const container = document.getElementById("sigma-container") as HTMLElement;
const renderer = new Sigma(graph, container, {
// Insert the metaballs depth layers between the edges and the nodes:
depthLayers: ["edges", ...communityDepths, "nodes", "topNodes"],
// Track active contour layer cleanup functions
const activeLayers: Record<string, (() => void) | null> = {};
function showContour(community: string) {
if (activeLayers[community]) return;
activeLayers[community] = bindWebGLLayer(
`community-${community}`,
graph.filterNodes((_, attr) => attr.community === community),
border: { color: palette[community], thickness: 8 },
levels: [{ color: palette[community] + "22", threshold: 0.5 }],
function hideContour(community: string) {
if (activeLayers[community]) {
activeLayers[community]!();
activeLayers[community] = null;
// Register a toggle per community
{ type: "toggle"; label: string; default: boolean; action: (active: boolean) => void }
communitiesArray.forEach((community, i) => {
controls[`community-${i}`] = {
if (active) showContour(community);
else hideContour(community);
registerControls(controls);
// Show the first community's contour on load
showContour(communitiesArray[0]);