Skip to content
This is the alpha v4 version website. Looking for the v3 documentation?

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:

InteractionMouseTouch
PanDrag the backgroundDrag with one finger
ZoomScroll wheelPinch
RotateRight-click dragTwo-finger rotate
HoverMove cursor over a node-
ClickClick a node, edge, or backgroundTap

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.