Turtles all the way down

Tue Jul 01 2025

Articles in the On Grids series

I've been meaning to get back into working with plotted generative art for some time now, and I have a few ideas for the development of a few posts about it. But in order to get there, I wanted a simple, SVG based canvas to create such artwork. There are a number of prebuilt options out there - paper.js, SCG.js etc. - but they're either too fully-featured or too opinionated for what I want to achieve.

Something that's always been really cool in this space is the turtle graphics API. It's super simple, and very easy to understand. It uses a convention of a turtle that has three attributes - location, orientation, and a pen. You send commands to the turtle to change one of these properties in a variety of ways, and it draws lines.

A turtle moving around and drawing a star.

The turtle moves around the canvas with simple-to-understand commands like forward, backward, left, right etc.

There is a fantastic website called Turtletoy, created and operated by the incredibly talented Reinder Nijhoff, that implements this API using javascript and provides a community tool to allow people to create and publish tutles. Make sure you check it out, there is some incredible work over there.

So I've created a simple class called Turtleman that allows me to create these sorts of drawings, you can check it out on codepen or github. This library provides a relatively simple API, as demonstrated here:

const toy = new Turtleman();
container.appendChild(toy.svg);
const squareCommands = `
  forward 100
  right 90
  forward 100
  right 90
  forward 100
  right 90
  forward 100
`;
toy.drawCommands(squareCommands);

What's cool about this is that you can generate some relatively complex drawings with relatively simple building blocks. Here's the code to generate the spiral in the above example:

 // Coil spacing
const tightness = .6;
 // The distance between points
const step_size = 3;
// Current angle in radians
let theta = 0;
// Current radius
let radius = .1; 
i = 0;
while (radius < 500) {
  const d_theta = step_size / 
    Math.sqrt(
      tightness * tightness + 
      radius * radius
    );
  theta += d_theta;
  radius = tightness * theta;
  let x = Math.cos(theta) * radius + 
    toy.width / 2;
  let y = Math.sin(theta) * radius + 
    toy.height / 2;
  toy.goto(x, y);
}

But with some relatively straightforward changes, you can create something which appears much more complex.

const tightness = .6;
const step_size = 3;
let theta = 0;
let radius = .1;
i = 0;
while (radius < 500) {
  const d_theta = step_size / 
    Math.sqrt(
      tightness * tightness + 
      radius * radius
    );
  theta += d_theta;
  radius = tightness * theta;
  let x = Math.cos(theta) * radius + 
    toy.width / 2;
  let y = Math.sin(theta) * radius + 
    toy.height / 2;

  const scale = .04;
  const size = 20;
  x += (
    Math.sin((x*scale)) + 
    Math.cos(y*scale)) * size;
  y += (
    Math.cos((x*scale)) + 
      Math.sin(y*scale)) * size;

  toy.goto(x, y);
}

What's next?

I think I want to do a series of posts on generative art using this system. Probably starting with a breakdown of grids and their uses with systems like this.