Interactions and events
Sigma handles mouse and touch interactions out of the box and emits events you can listen to.
Built-in interactions
By default, sigma supports these interactions:
| Interaction | Mouse | Touch |
|---|---|---|
| Pan | Drag the background | Drag with one finger |
| Zoom | Scroll wheel | Pinch |
| Rotate | Right-click drag | Two-finger rotate |
| Hover | Move cursor over a node | - |
| Click | Click a node, edge, or background | Tap |
Some of these interactions can be enabled or disabled via settings:
new Sigma(graph, container, { settings: { enableCameraZooming: true, // Scroll/pinch to zoom enableCameraPanning: true, // Drag to pan enableCameraRotation: true, // Right-click drag / two-finger rotate },});Listening for events
Sigma emits events when users interact with nodes, edges, or the stage (background). Listen with renderer.on():
renderer.on("clickNode", ({ node, event }) => { console.log("Clicked node", node); console.log("Position", event.x, event.y); console.log("Native event", event.original);});
renderer.on("enterNode", ({ node }) => { console.log("Entering node", node);});
renderer.on("leaveNode", ({ node }) => { console.log("Entering node", node);});
renderer.on("clickStage", () => { // User clicked the background, e.g. deselect all});Every event payload includes an event object with x, y coordinates and original (the native MouseEvent or TouchEvent).
Enabling edge events
Edge events are disabled by default for performance (edge hit detection requires extra GPU work). Enable them with:
new Sigma(graph, container, { settings: { enableEdgeEvents: true },});Live example
Interact with the graph below. Every event is logged in the overlay panel.
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); });});For the full list of events and their payloads, see the Events reference.