<div id="sigma-container"></div>
<div id="sigma-logs"></div>
<style>
#sigma-container {
width: 100%;
height: 100%;
font-family: sans-serif;
}
#sigma-container .sigma-mouse {
z-index: 1;
}
:global(#sigma-logs) {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
}
:global(#sigma-logs > div) {
padding: 3px;
}
:global(#sigma-logs > div > span) {
background: #ffffff99;
}
</style>
<script>
import Graph from "graphology";
import Sigma from "sigma";
import {
DEFAULT_STYLES,
type MouseCoords,
type SigmaEdgeEventPayload,
type SigmaEdgeLabelEventPayload,
type SigmaNodeEventPayload,
type SigmaNodeLabelEventPayload,
type SigmaStageEventPayload,
} from "sigma/types";
import data from "../_data/data.json";
const container = document.getElementById("sigma-container") as HTMLElement;
const logsDOM = document.getElementById("sigma-logs") as HTMLElement;
const graph = new Graph();
graph.import(data);
graph.forEachEdge((edge, attributes) => {
graph.setEdgeAttribute(edge, "label", `cooccurences: ${attributes.size}`);
});
function logEvent(event: string, itemType: "node" | "edge" | "positions", item: string | MouseCoords): void {
const div = document.createElement("div");
let message = `"${event}"`;
if (item && itemType) {
if (itemType === "positions") {
item = item as MouseCoords;
message += `, x ${item.x}, y ${item.y}`;
} else {
const label =
itemType === "node" ? graph.getNodeAttribute(item, "label") : graph.getEdgeAttribute(item, "label");
message += `, ${itemType} ${label || "with no label"} (id "${item}")`;
if (itemType === "edge") {
message += `, source ${graph.getSourceAttribute(item, "label")}, target: ${graph.getTargetAttribute(
item,
"label",
)}`;
}
}
}
div.innerHTML = `<span>${message}</span>`;
logsDOM.appendChild(div);
logsDOM.scrollTo({ top: logsDOM.scrollHeight });
if (logsDOM.children.length > 50) logsDOM.children[0].remove();
}
const renderer = new Sigma(graph, container, {
settings: {
enableEdgeEvents: true,
nodeLabelEvents: "separate",
edgeLabelEvents: "separate",
renderEdgeLabels: true,
edgePickingPadding: 30,
},
styles: {
edges: [
DEFAULT_STYLES.edges,
{ labelPosition: "above" },
{ whenState: "isHovered", then: { color: "#cc0000" } },
{ whenState: "isLabelHovered", then: { labelColor: "#cc0000", labelDepth: "topEdges" } },
],
nodes: [
DEFAULT_STYLES.nodes,
{ whenState: "isLabelHovered", then: { labelColor: "#cc0000", depth: "topNodes" } },
],
},
});
const nodeEvents = [
"enterNode",
"leaveNode",
"downNode",
"clickNode",
"rightClickNode",
"doubleClickNode",
"wheelNode",
] as const;
const edgeEvents = [
"enterEdge",
"leaveEdge",
"downEdge",
"clickEdge",
"rightClickEdge",
"doubleClickEdge",
"wheelEdge",
] as const;
const nodeLabelEvents = [
"enterNodeLabel",
"leaveNodeLabel",
"downNodeLabel",
"upNodeLabel",
"clickNodeLabel",
] as const;
const edgeLabelEvents = [
"enterEdgeLabel",
"leaveEdgeLabel",
"downEdgeLabel",
"upEdgeLabel",
"clickEdgeLabel",
] as const;
const stageEvents = ["downStage", "clickStage", "doubleClickStage", "wheelStage"] as const;
nodeEvents.forEach((eventType) => {
renderer.on(eventType, ({ node }: SigmaNodeEventPayload) => {
logEvent(eventType, "node", node);
});
});
edgeEvents.forEach((eventType) => {
renderer.on(eventType, ({ edge }: SigmaEdgeEventPayload) => {
logEvent(eventType, "edge", edge);
});
});
nodeLabelEvents.forEach((eventType) => {
renderer.on(eventType, ({ node }: SigmaNodeLabelEventPayload) => {
logEvent(eventType, "node", node);
});
});
edgeLabelEvents.forEach((eventType) => {
renderer.on(eventType, ({ edge }: SigmaEdgeLabelEventPayload) => {
logEvent(eventType, "edge", edge);
});
});
stageEvents.forEach((eventType) => {
renderer.on(eventType, ({ event }: SigmaStageEventPayload) => {
logEvent(eventType, "positions", event);
});
});
</script>