Solandra

A human friendly framework for creative coding with TypeScript

Start here

  1. Browse the examples. Each sketch includes its source code.
  2. Follow the getting started guide
  3. For coding assistants, add the API reference to your project.
  4. Or follow the tutorial below to build an animated sketch.

Slideshow

Use the arrow keys or click to change sketches.

Principles

I built Solandra to make sketches easy to change and experiment with. My essays describe the ideas behind it.

  • Use TypeScript for autocomplete and type checking.
  • Assume some JavaScript or TypeScript experience.
  • Work with tiles, rows and shapes in drawing loops.
  • Prioritise quick experimentation over rendering speed.
  • Provide helpers for common tasks such as seeded randomness.
  • Describe shapes with configuration objects and draw them with ordinary functions and loops.

Practice

Some of the practical implications:

  • Sketches always have width 1, height depends on aspect ratio.
  • Angles in radians.
  • Points are [number, number].
  • Colours in hsl(a).
  • Describe curves by their size, direction and shape.

Tutorial

Build the animated logo above, starting with its background. Colours use HSL: hue (0–360), saturation (0–100) and lightness (0–100), with optional alpha (0–1) for opacity.

A sketch is a function that takes an SCanvas, called p in these examples.

p.background(220, 26, 14)

Set a fill colour, then pass a shape to fill. To stroke its outline, use draw instead.

p.setFillColor(220, 54, 50) 
p.fill(new Rect({ at: [0.2, 0.2], w: 0.6, h: 0.4 }))

Points use [x, y] coordinates. Common options have short names, such as w for width.

Use forTiling to repeat the shape across a grid:

p.forTiling({ n: 10, type: "square", margin: 0.1 },
    (at, [w, h], c, i) => {
        p.setFillColor(150 + i * 5, 54, 50)
        p.fill(new Rect({ at, w, h }))
    })

The configuration sets ten square tiles across, with a margin around the canvas.

The callback receives each tile's position, size, centre and index. Here, the index determines its colour.

Next, use forHorizontal to draw a row of polygons. It takes the same callback arguments as forTiling:

p.forHorizontal({ n: 8, margin: 0.1 }, (at, [w, h], c, i) => {
    p.setFillColor(150 + i * 5, 54, 50)
    p.fill(new RegularPolygon({ at: c, r: w / 3, n: i + 3 }))
})

Use p.t, the time in seconds, to animate the polygons. Sine and cosine make their properties vary smoothly:

new RegularPolygon({
        at: [c[0], c[1] + Math.cos(p.t + (i * Math.PI) / 8) * 0.2],
        r: w / 3,
        n: i + 3,
    })

Combine these steps to draw the animated logo:

p.background(220, 26, 14)
const { bottom, right, center } = p.meta
const d = Math.min(bottom, right) / 2.8

p.times(5, n => {
    const sides = 10 - n
    const r = d - n * 0.16 * d + (1 + Math.cos(p.t)) / 40
    p.setFillColor(220, 70, 10 + n * 12)
    p.fill(new RegularPolygon({
        at: center,
        n: sides,
        r,
    }))
})

Examples

Explore more sketches and their source code:

Other Platforms

Versions of Solandra are available on other platforms

Solandra was made by James Porter.

Check out the GitHub page or install with npm i solandra