Menu

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.

16x16
32x32
48x48
64x64

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.

0 (square)
0.5 (rounded)
1 (circle)

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.
Solid
Gradient static
Gradient animated
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

FeatureDot Matrix
Responsive scalingManual (fixed canvas)
Trail costFlat per frame regardless of grid size
AccessibilityAdd a visually hidden label
Animated gradientsYes
Custom palettesYes

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:

OptionTypeDefaultDescription
colsnumber32Number of dot columns
rowsnumber32Number of dot rows
roundnessnumber1Dot shape. 0 = square, 1 = circle
trailLengthnumbercols * 3Trail length. Larger values extend the tail further
autoStartbooleantrueStart animation on creation
initialPhasenumberundefinedInitial position along the curve
pauseOnHiddenbooleantruePause when tab is hidden

Runtime options: update live via setRenderOptions without recreating:

OptionTypeDefaultDescription
trailColorstring | string[]'#ffffff'Dot color. Array enables gradient modes
trailStyleTrailStyle'default''default', 'gradient-static', or 'gradient-animated'
skeletonColorstring'#ffffff'Color of the background skeleton dots. Use 'transparent' to hide
gridColorstringundefinedColor of the background dot grid at 5% opacity. Use 'transparent' to hide

See the API Reference for full details on each option.

See Also