Dot Matrix
The dot matrix renderer maps Sarmal curves onto a grid of dots. Each dot’s brightness reflects its position along the trail. The head dot is fully lit, and as the position travels toward the tail, it becomes to fade. The background grid is visible by default. You can hide it for logos, icons, or light backgrounds where background dots read as noise.
How It Works
Each frame, trail points are mapped to grid cells. Adjacent points are gap-filled so no cell is skipped, even at coarse densities. Each lit dot gets an intensity from 0 to 1 based on its position in the trail. The final frame is written in a single putImageData call. Performance is flat regardless of grid size.
Grid Density
Grid density is the most visible dial. Coarser grids feel pixelated. Finer grids approximate continuous motion while preserving the dot character.
The default is 32x32. It’s a sweet middle ground where the curve has the dot matrix character, but also fine enough to retain its shape. The trail length defaults to cols * 3, so the tail stays proportional regardless of density.
Dot Shape
roundness controls dot shape the same way CSS border-radius controls corners: 0 is a sharp square, 1 is a full circle, anything in between is a rounded rectangle.
Color Modes
The same three modes as the canvas and svg renderers:
- Solid (
"default"): Single color, brightness varies by trail position. - Gradient static (
"gradient-static"): Each dot’s color is sampled from the palette by its trail position. The palette doesn’t move. - Gradient animated (
"gradient-animated"): same, but the palette shifts as the head advances.
import { createSarmalDotMatrix, palettes } from "@sarmal/core";
// Solid color
createSarmalDotMatrix(canvas, curve, { trailColor: "#2dd4bf" });
// Static gradient
createSarmalDotMatrix(canvas, curve, {
trailColor: palettes.rocketpop,
trailStyle: "gradient-static",
});
// Animated gradient
createSarmalDotMatrix(canvas, curve, {
trailColor: palettes.ice,
trailStyle: "gradient-animated",
});
Skeleton
Behind the trail, a faint layer of dots outlines the full curve path. This is the skeleton, and it has its own color (skeletonColor), which is separate from the trail.
The default is white, which disappears on light backgrounds. Set it to something that reads against your surface, or pass "transparent" to remove it:
createSarmalDotMatrix(canvas, curve, {
trailColor: "#2dd4bf",
skeletonColor: "#3a3b37",
});
// No skeleton
createSarmalDotMatrix(canvas, curve, {
trailColor: "#2dd4bf",
skeletonColor: "transparent",
});
Grid Background
By default, every grid cell shows a faint dot at 5% opacity using the trail’s primary color. This gives the grid texture its “blueprint” feel.
gridColor lets you change or disable the background dot layer at any time:
// Disable background dots
createSarmalDotMatrix(canvas, curve, {
trailColor: "#2dd4bf",
gridColor: "transparent",
});
// Custom color
createSarmalDotMatrix(canvas, curve, {
trailColor: "#2dd4bf",
gridColor: "#e2e8f0",
});
// Set live without recreating the instance
instance.setRenderOptions({ gridColor: "transparent" });
When omitted, the background dots use the trail’s primary* color. Setting gridColor to any value other than "transparent" overrides the color while keeping the 5% opacity.
Morphing
morphTo works the same as on the canvas and SVG renderers. The dot grid adapts frame by frame as the trail fills with points from the new curve.
const sarmal = createSarmalDotMatrix(canvas, curves.lissajous43, {
trailColor: "#2dd4bf",
});
await sarmal.morphTo(curves.deltoid);
// Custom duration and strategy
await sarmal.morphTo(curves.rose3, { duration: 600, morphStrategy: "normalized" });
See Morphing in Getting Started for the full model.
When to Use
Reach for the dot matrix when:
- You want a blueprint, schematic, or technical aesthetic
- The indicator should fill space without demanding attention
- You want the ambient texture of a full grid, not a ribbon
Skip it when you need smooth continuous motion, or when the canvas needs accessibility semantics.
Characteristics
| Feature | Dot Matrix |
|---|---|
| Responsive scaling | Manual (fixed canvas) |
| Trail cost | Flat per frame regardless of grid size |
| Accessibility | Add a visually hidden label |
| Animated gradients | Yes |
| Custom palettes | Yes |
Usage
import { createSarmalDotMatrix, curves } from "@sarmal/core";
const canvas = document.getElementById("loader") as HTMLCanvasElement;
const sarmal = createSarmalDotMatrix(canvas, curves.lissajous43, {
cols: 32,
rows: 32,
roundness: 1,
trailColor: "#2dd4bf",
});
Returns the same SarmalInstance interface as createSarmal and createSarmalSVG. All instance methods (play, pause, morphTo, seek, setRenderOptions, destroy) work identically.
Options
Init options: changing any of these destroys and recreates the instance:
| Option | Type | Default | Description |
|---|---|---|---|
| cols | number | 32 | Number of dot columns |
| rows | number | 32 | Number of dot rows |
| roundness | number | 1 | Dot shape. 0 = square, 1 = circle |
| trailLength | number | cols * 3 | Trail length. Larger values extend the tail further |
| autoStart | boolean | true | Start animation on creation |
| initialPhase | number | undefined | Initial position along the curve |
| pauseOnHidden | boolean | true | Pause when tab is hidden |
Runtime options: update live via setRenderOptions without recreating:
| Option | Type | Default | Description |
|---|---|---|---|
| trailColor | string | string[] | '#ffffff' | Dot color. Array enables gradient modes |
| trailStyle | TrailStyle | 'default' | 'default', 'gradient-static', or 'gradient-animated' |
| skeletonColor | string | '#ffffff' | Color of the background skeleton dots. Use 'transparent' to hide |
| gridColor | string | undefined | Color of the background dot grid at 5% opacity. Use 'transparent' to hide |
See the API Reference for full details on each option.
See Also
- Canvas vs SVG: choose the right ribbon renderer
- API Reference: full options and methods
- Terminal & CLI: sarmal in the terminal