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

Paths and colors

Sigma v4 gives you full control over edge appearance through the primitives and styles system. You can combine different path geometries and fill layers.

import Graph from "graphology";
import Sigma, { DEFAULT_STYLES } from "sigma";
import {
extremityArrow,
layerDashed,
layerFill,
layerGradient,
layerPlain,
pathCurved,
pathCurvedS,
pathLine,
pathStepCurved,
sdfCircle,
sdfTriangle,
} from "sigma/rendering";
const container = document.getElementById("sigma-container") as HTMLElement;
const SOURCE_COLOR = "#7E3D9C";
const TARGET_COLOR = "#ED8666";
// Each row has its own path:
const PATHS = ["straight", "curved", "stepCurved", "curvedS"] as const;
// Each column shows edges fillings and extremities in its own way:
const COLUMNS = [
{ useGradient: true },
{ head: "arrow" },
{ head: "arrow", tail: "arrow", useGradient: true },
{ dashSize: 5, dashColor: "#ffffff99" },
{ head: "arrow", dashSize: 10, dashColor: "#ffffff99", useGradient: true },
];
const graph = new Graph();
PATHS.forEach((path, row) => {
COLUMNS.forEach((config, col) => {
const [x, y] = [col * 120, -row * 80];
const source = graph.addNode(`${path}-${col}-source`, { x: x - 30, y, color: SOURCE_COLOR });
const target = graph.addNode(`${path}-${col}-target`, {
x: x + 30,
y: y + 30,
color: TARGET_COLOR,
shape: "triangle",
});
graph.addEdge(source, target, { size: 6, path, curvature: path === "curved" ? 0.3 : 0, ...config });
});
});
new Sigma(graph, container, {
primitives: {
nodes: {
shapes: [sdfCircle(), sdfTriangle()],
layers: [layerFill()],
},
edges: {
variables: {
dashColor: { type: "color", default: "#000" },
dashSize: { type: "number", default: 0 },
useGradient: { type: "boolean", default: false },
},
paths: [pathLine(), pathCurved(), pathStepCurved(), pathCurvedS()],
extremities: [extremityArrow()],
layers: [
layerPlain({ color: { node: "source" } }),
layerGradient({
stops: [{ node: "source" }, { node: "target" }],
enabled: { attribute: "useGradient" },
}),
layerDashed({
dashColor: { attribute: "dashColor" },
dashSize: { attribute: "dashSize" },
gapSize: { value: 10 },
}),
],
},
},
styles: {
nodes: [DEFAULT_STYLES.nodes, { size: 12, shape: { attribute: "shape" } }],
edges: [
DEFAULT_STYLES.edges,
{ path: { attribute: "path" }, head: { attribute: "head" }, tail: { attribute: "tail" } },
],
},
settings: {
renderEdgeLabels: true,
itemSizesReference: "positions",
autoRescale: true,
},
});

Edge paths

Sigma ships with five built-in path types:

PathDescription
pathLine()Direct line between source and target
pathCurved()Quadratic Bezier curve (configurable curvature)
pathStep()Right-angle step (horizontal then vertical)
pathStepCurved()Step with rounded corners
pathCurvedS()S-shaped cubic curve

Declare which paths your graph uses in primitives.edges.paths, then assign them per-edge via styles.

For arrowheads and other endpoint shapes, see the Extremities documentation.

Edge colors

Edge colors work like node colors. Set them in the graph data and read them via styles:

graph.addEdge("a", "b", { color: "#e63946" });
new Sigma(graph, container, {
styles: {
edges: [{ color: { attribute: "color" } }],
},
});

Edge layer color options (like layerPlain()’s color, or layerDashed()’s dashColor and gapColor) accept three forms:

  • A constant CSS color string (e.g. "#e63946");
  • { attribute } to read a per-edge color from graph data;
  • { node: "source" } or { node: "target" } to use an endpoint node’s color.

Node references are read live from the GPU: edges follow their node’s color through hover effects and state changes, with no per-edge data to maintain.

new Sigma(graph, container, {
primitives: {
edges: {
// Every edge wears its source node's color:
layers: [layerPlain({ color: { node: "source" } })],
},
},
});

Dashed edges

The layerDashed() function from sigma/rendering adds a dashed overlay on top of the plain edge body. The dashSize and gapSize options accept either a fixed { value, mode } object or an { attribute } reference to read per-edge values from graph data. Set mode: "pixels" for screen-space sizing.

The cap option controls the shape of dash ends: "butt" (the default) gives straight ends, while "round" gives round caps. Round-capped dashes shorter than the edge thickness degenerate to circles, so dotted edges are simply:

layerDashed({ cap: "round", dashSize: { value: 1, mode: "relative" }, gapSize: { value: 2, mode: "relative" } });

Gradient edges

The layerGradient() function from sigma/rendering fills the edge with a gradient along a list of color stops, from the source end to the target end. Each stop accepts any of the color forms above, so the typical use is blending the endpoint node colors:

new Sigma(graph, container, {
primitives: {
edges: {
layers: [layerGradient({ stops: [{ node: "source" }, { node: "target" }] })],
},
},
});

Stops follow the same positioning rules as CSS gradients: an optional offset in [0, 1] places a stop along the visible edge span, the first stop defaults to 0, the last to 1, and stops without an offset spread evenly between their positioned neighbors. Past the outermost offsets, the gradient pads with the nearest stop’s color. The offset field sits directly on { node } and { attribute } stops, and constant colors take the { color, offset } form.

// Fade through transparent halfway:
layerGradient({ stops: [{ node: "source" }, "transparent", { node: "target" }] });
// Show only a short stub leaving the source node:
layerGradient({ stops: [{ node: "source" }, { color: "transparent", offset: 0.1 }] });
// Hard switch from source to target color at the midpoint:
layerGradient({
stops: [
{ node: "source", offset: 0.5 },
{ node: "target", offset: 0.5 },
],
});

The optional enabled option reads a boolean edge attribute to toggle the gradient per edge; disabled edges fall through to the layers below.

For more on the styles and primitives system, see Styles and primitives.