Skip to content
sigma.js sigma.js
v4.0.6 Docs Examples GitHub 12.2K

Fill layers

Node appearance is built by compositing layers from back to front. These layers determine “how to colorize each pixel” within a node’s shape. Sigma ships with one built-in layer (layerFill), and three extension packages add specialized layers for borders, images, and piecharts.

Layers are declared in primitives.nodes.layers. They are composited in order: earlier layers render behind later ones. Layers automatically disable themselves when they have no data for a given node (e.g., an image layer on a node without an image attribute renders as transparent).

All nodes share the same WebGL program, with the same shaders, regardless of which layers they use.

Layer Package Description
layerFill() sigma/rendering Solid color fill using the node’s color
layerBorder() @sigma/node-border Configurable concentric borders
layerImage() @sigma/node-image Image or pictogram rendered inside the shape
layerPiechart() @sigma/node-piechart Pie chart slices

The @sigma/node-border package adds one or more concentric borders around nodes. Each border entry has a size (fraction of node radius), a color, and optional fill: true to fill the remaining space. Set mode: "pixels" for fixed pixel widths. Border sizes and colors can also be read from node attributes using { attribute: "..." }.

import { layerBorder } from "@sigma/node-border";
import Sigma from "sigma";
import { getSmallGraph } from "../_data/small-graph";
const container = document.getElementById("sigma-container") as HTMLElement;
const graph = getSmallGraph();
const BORDER_COLORS: Record<string, string> = {
a: "darkgrey",
b: "darkgrey",
c: "darkgrey",
d: "lightgrey",
e: "lightgrey",
f: "lightgrey",
};
graph.forEachNode((node) => {
graph.setNodeAttribute(node, "borderColor", BORDER_COLORS[node]);
});
new Sigma(graph, container, {
primitives: {
nodes: {
variables: {
borderColor: { type: "color", default: "red" },
},
layers: [
layerBorder({
borders: [
{ size: 0.3, color: { attribute: "borderColor" }, mode: "relative" },
{ size: 0, color: { attribute: "color" }, fill: true },
],
}),
],
},
},
});

The @sigma/node-image package renders photos or SVG icons inside nodes. The image is clipped to the node shape. For SVG pictograms, use drawingMode: "color" to tint the icon with the node’s color, and padding to add space around the icon.

import { layerImage } from "@sigma/node-image";
import Sigma from "sigma";
import { layerFill } from "sigma/rendering";
import { getSmallGraph } from "../_data/small-graph";
const container = document.getElementById("sigma-container") as HTMLElement;
const graph = getSmallGraph();
const IMAGES: Record<string, { label: string; image?: string }> = {
a: {
label: "Jim",
image: "https://upload.wikimedia.org/wikipedia/commons/7/7f/Jim_Morrison_1969.JPG",
},
b: {
label: "Johnny",
image: "https://upload.wikimedia.org/wikipedia/commons/a/a8/Johnny_Hallyday_%E2%80%94_Milan%2C_1973.jpg",
},
c: {
label: "Jimi",
image: "https://upload.wikimedia.org/wikipedia/commons/6/6c/Jimi-Hendrix-1967-Helsinki-d.jpg",
},
d: {
label: "Bob",
image:
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Bob-Dylan-arrived-at-Arlanda-surrounded-by-twenty-bodyguards-and-assistants-391770740297_%28cropped%29.jpg",
},
e: {
label: "Eric",
image: "https://upload.wikimedia.org/wikipedia/commons/b/b1/Eric_Clapton_1.jpg",
},
f: {
label: "John Doe",
},
};
graph.forEachNode((node) => {
graph.mergeNodeAttributes(node, IMAGES[node]);
});
new Sigma(graph, container, {
primitives: {
nodes: {
variables: {
image: { type: "string", default: "/img/placeholder-node-image.png" },
},
layers: [layerFill(), layerImage()],
},
},
});

The @sigma/node-piechart package renders nodes as pie charts. Slice proportions are computed automatically. Set defaultColor to control the appearance when all values are zero. Use offset (radians) to rotate the starting angle.

import { layerPiechart } from "@sigma/node-piechart";
import iwanthue from "iwanthue";
import seedrandom from "seedrandom";
import Sigma from "sigma";
import { registerControls } from "../_controls";
import { getSmallGraph } from "../_data/small-graph";
const container = document.getElementById("sigma-container") as HTMLElement;
const { slices } = registerControls({
slices: { type: "number", label: "Slices", default: 3, min: 1, max: 32, step: 1 },
});
const graph = getSmallGraph();
const rng = seedrandom("sigma");
const palette = iwanthue(slices, { seed: "sigma", colorSpace: "green-mint" });
const sliceKeys = Array.from({ length: slices }, (_, i) => `slice${i}`);
graph.forEachNode((node) => {
sliceKeys.forEach((key) => {
// Node "d" stays empty to showcase defaultColor
graph.setNodeAttribute(node, key, node === "d" ? 0 : Math.max(rng() ** 2 - 0.01, 0));
});
});
new Sigma(graph, container, {
primitives: {
nodes: {
variables: Object.fromEntries(sliceKeys.map((key) => [key, { type: "number", default: 0 }])),
layers: [
layerPiechart({
defaultColor: "#BCB7C4",
slices: sliceKeys.map((key, i) => ({
color: palette[i],
value: { attribute: key },
})),
}),
],
},
},
});

Layers compose naturally. The example below combines a fill, a border and an image layer, composited in declaration order:

import { layerBorder } from "@sigma/node-border";
import { layerImage } from "@sigma/node-image";
import Sigma from "sigma";
import { layerFill } from "sigma/rendering";
import { getSmallGraph } from "../_data/small-graph";
const container = document.getElementById("sigma-container") as HTMLElement;
const graph = getSmallGraph();
const IMAGES: Record<string, { label: string; image?: string }> = {
a: {
label: "Jim",
image: "https://upload.wikimedia.org/wikipedia/commons/7/7f/Jim_Morrison_1969.JPG",
},
b: {
label: "Johnny",
image: "https://upload.wikimedia.org/wikipedia/commons/a/a8/Johnny_Hallyday_%E2%80%94_Milan%2C_1973.jpg",
},
c: {
label: "Jimi",
image: "https://upload.wikimedia.org/wikipedia/commons/6/6c/Jimi-Hendrix-1967-Helsinki-d.jpg",
},
d: {
label: "Bob",
image:
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Bob-Dylan-arrived-at-Arlanda-surrounded-by-twenty-bodyguards-and-assistants-391770740297_%28cropped%29.jpg",
},
e: {
label: "Eric",
image: "https://upload.wikimedia.org/wikipedia/commons/b/b1/Eric_Clapton_1.jpg",
},
f: {
label: "John Doe",
},
};
graph.forEachNode((node) => {
graph.mergeNodeAttributes(node, IMAGES[node]);
});
new Sigma(graph, container, {
primitives: {
nodes: {
variables: {
image: { type: "string", default: "/img/placeholder-node-image.png" },
},
layers: [
layerFill({ color: "lightgrey" }),
layerImage(),
layerBorder({
borders: [
{ size: 0.2, color: "#333" },
{ size: 0.2, color: "#fff" },
{ color: "transparent", fill: true },
],
}),
],
},
},
});