ewan's projects — docs
← all docs

@ewanc26/noise

March 13, 2026 3 min read
typescriptcanvassveltelibrarypkgs

@ewanc26/noise is the underlying noise engine extracted from @ewanc26/noise-avatar. It generates deterministic value-noise pixel data from an arbitrary string seed — same seed always produces the same output. It supports arbitrary canvas dimensions, multi-octave fractal Brownian motion (FBM), and several colour modes. Zero runtime dependencies; works anywhere with a Uint8ClampedArray — browsers, Node.js, and workers.

Part of the @ewanc26/pkgs monorepo.

Install

pnpm add @ewanc26/noise

Ships as both ESM and CJS with full TypeScript type definitions.

Usage

Raw pixels (no DOM required)

import { generateNoisePixels } from '@ewanc26/noise';

const pixels = generateNoisePixels(256, 256, 'my-seed', {
  octaves: 4,
  colorMode: { type: 'grayscale' },
});
// pixels is a Uint8ClampedArray of RGBA values (256 * 256 * 4 bytes)

Canvas

import { renderNoise } from '@ewanc26/noise';

const canvas = document.querySelector('canvas');
renderNoise(canvas, 'my-seed', { size: 128, octaves: 3 });

Svelte action

<script>
  import { noiseAction } from '@ewanc26/noise';

  let seed = 'my-seed';
</script>

<canvas use:noiseAction={{ seed, size: 128, octaves: 3 }}></canvas>

The action re-renders reactively whenever params changes.

API

generateNoisePixels(width, height, seed, options?)

Generates raw RGBA pixel data with no canvas or DOM required. Returns a Uint8ClampedArray of length width * height * 4.

renderNoise(canvas, seed, options?)

Renders noise onto an existing HTMLCanvasElement, resizing it to width/height/size first.

noiseAction(canvas, params)

Svelte action wrapper around renderNoise. Params: { seed, ...NoiseOptions, width?, height?, size? }.

Noise options

Option Type Default Description
gridSize number 5 Noise grid resolution
octaves number 1 FBM octave count — 1 = plain value noise
persistence number 0.5 FBM amplitude falloff per octave
lacunarity number 2 FBM frequency multiplier per octave
colorMode ColorMode { type: 'hsl' } How noise values map to colours

Render options

Option Type Default Description
width number 64 Canvas width in pixels
height number 64 Canvas height in pixels
size number — Shorthand to set width and height equally

Colour modes

{ type: 'hsl' } — hue is derived from the seed, and the noise value shifts hue, saturation, and lightness within configurable ranges.

Option Type Default
hueRange number 60
saturationRange [number, number] [45, 70]
lightnessRange [number, number] [40, 70]

{ type: 'grayscale' } — noise value maps directly to luminance.

Option Type Default
range [number, number] [0, 255]

{ type: 'palette', colors } — noise value interpolates smoothly through an ordered list of RGB colours.

colorMode: {
  type: 'palette',
  colors: [[0, 0, 128], [0, 200, 255], [255, 255, 255]],
}

Core primitives

Export Description
hash32(str) djb2 hash → unsigned 32-bit integer
makePrng(seed) Seeded LCG PRNG → () => float in [0, 1)
hslToRgb(h, s, l) HSL (components in [0, 1]) → RGB triple ([0, 255])
makeValueNoiseSampler(gridSize, rng) Returns (nx, ny) → float in [0, 1] value-noise sampler

Examples

// Multi-octave FBM with a cool-toned palette
renderNoise(canvas, 'landscape', {
  size: 256,
  octaves: 5,
  persistence: 0.6,
  colorMode: {
    type: 'palette',
    colors: [[10, 10, 60], [30, 80, 160], [180, 220, 255]],
  },
});

// Simple grayscale heightmap, no canvas
const heightmap = generateNoisePixels(512, 512, 'terrain-seed', {
  gridSize: 8,
  octaves: 6,
  colorMode: { type: 'grayscale' },
});

Relation to noise-avatar

@ewanc26/noise-avatar is a thin opinionated wrapper around this package. It fixes the colour mode to HSL and defaults to a square 64×64 canvas, so you don't have to think about noise options for the common avatar use-case. Use @ewanc26/noise directly when you need non-square dimensions, FBM octaves, or grayscale/palette colour modes.

Licence

AGPL-3.0-only — see the pkgs monorepo.


← all docs