ewan's projects — docs

projects

@ewanc26/noise

March 13, 2026

# typescript# canvas# svelte# library# pkgs

@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