Tiny Generative Art Template

A screenshot of Windows Terminal that shows the directory structure of the project.

I’ve been using canvas-sketch ever since I started learning generative art back in November. It’s an incredibly useful tool for creating a new project, setting up a local server, and saving my artwork to disk. The only issue that I have with it is that it comes with a lot of dependencies that I don’t think are necessary for the kind of art that I do.

So I thought that I could take a stab at creating a minimal generative art template that only includes the things that I need. This is is how it works:

Screencast showing a demo of the project. You can try it out yourself here: ~jagtalon/generative-art-template

It’s not a zero-dependency template, but as long as you have CoffeeScript and Browsersync installed, you should be good to go. To start a new project, all you need to do is:

  1. Download or clone the template.
  2. Run ./build.sh (runs the CoffeeScript compiler)
  3. Run ./server.sh (runs the Browsersync server)

And you’re good to go! The two most important files in it are index.html and art.coffee:

  • πŸ’» index.html is a barebones HTML file that lets me view and save the artwork. It has a little bit of CSS that makes the Canvas responsive (I often work with large 3600×5400 images!) and a little bit of JavaScript that lets me download the art.
  • 🎨 art.coffee is where I draw. It’s written in CoffeeScript, and it’s compiled to JS. I’m using it as a JavaScript module so that I can easily import libraries that are both local (like my little Canvas API wrapper called tiny-canvas.coffee) and remote (like NPM modules on Skypack).
Screencast showing how short the index.html and art.coffee files are.

And that’s it! build.sh and server.sh are set up to watch the files for any changes, so there’s no reloading involved once these two are running.

Of course, I could get really lean by removing the dependency on CoffeeScript, but I personally enjoy working with this language so I decided to include it. If you’re interested in tweaking the setup, feel free to fork the project and modify the template to your needs! You can find the repository on Sourcehut.

Long-Exposure Art

A photo of my night sky art on my table. There's also a toy dog beside it for scale.

I’ve been fascinated with long-exposure shots of the night sky recently (like this one), so I thought it would be fun to emulate that effect on <canvas>. I assumed that it would take me a while to figure it out, but the algorithm turned out to be surprisingly simple!

The first thing I noticed was that each “star trail” is basically a small segment of a circle, so I figured that I’d be using the arc() method a lot. After staring at different long-exposure photos, I also noticed that the star trails grow in length as it moves farther away from the center of the spiral. This told me that the angle that I’ll use for the arc will probably be constant throughout the artwork. The only thing that needed to change was the radius of that arc.

But how do I draw multiple arcs across the canvas? My first solution was to generate random x-y coordinates all over the page and then get the distance between (0, 0) and (x, y) using Math.hypot(). I then created an arc for each point using the distance as its radius and then spun it around to a random angle using rotate(). It looked something like this in CoffeeScript:

# For each point:
# 1. Find the distance between (0,0) and (x,y)
# 2. Create an arc with constant theta
# 3. Rotate it to a random angle (Math.random() * 2Ο€)
drawStarTrails = (x, y) ->
    context.arc 0, 0, Math.hypot(x, y), 0, theta
    ...
    context.rotate Math.random() * 2 * Math.PI

# Draw random x-y coordinates
drawStarTrails(Math.random() * width, Math.random() * height) for n in [1..1000]

But then I realized that I didn’t need to find the distance between (0, 0) and a random point at all. I could just plug in a random radius and I’d get the same effect:

# For each iteration:
# 1. Find a random radius.
# 2. Create an arc with constant theta
# 2. Rotate it to a random angle (Math.random() * 2Ο€)
drawStarTrails = () ->
    context.arc 0, 0, Math.random() * width, 0, theta
    ...
    context.rotate Math.random() * 2 * Math.PI

# Create the star trails
drawStarTrails() for n in [1..1000]

And that was it! Now it took me a couple of hours fiddling with different colors, gradients, angles, stroke widths, and the number of arcs to get it to look right (the final version has 9000 arcs!), but this project reminded me how simple rules could generate something that looks complex. It’s honestly one of my favorite things about generative art.

You can find the complete source code on Sourcehut. You can also get prints in digital and physical formats (if it’s in stock) here πŸ–Ό.

This is the final version of the artwork. You can find the source code here if you’d like to read the whole program or make modifications yourself.

Two Posters of Space

A print of my art of a spiral on top of my keyboard.

I recently made two space-themed posters, and I think they turned out pretty nicely! The first one that I made was honestly a bit of an accident. My initial goal was to create a sunflower, so I watched some YouTube videos on how spirals work, and I also read some code online to learn how they’re implemented as a program.

But as I played around with different spiral styles and backgrounds, I decided that it was better to go with this galaxy/wormhole poster instead.

I was really happy with how this poster came out, so I thought it would be fun to continue working on space art. A planet felt like a good next step, so I made this gas giant poster next. The planet itself is a circle with a gradient fill, and the rings are ellipses with a gradient stroke.

A green-blue gas giant floating in a sea of stars. You can find the code here.

It’s a pretty simple illustration, but I think the fun part was implementing this in Lisp. I used Lisp instead of JavaScript this time because I wanted to try out this experimental image processing tool called Ronin. I don’t have much experience programming in Lisp, but it felt perfect for generative art. It didn’t look as verbose or as cryptic when compared to using the Canvas API directly. If I wanted to draw a star, I could simply write:

(fill
    (circle x y radius) "#DEE2E6")

Instead of:

context.fillStyle = "#DEE2E6";
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, true);
context.fill();
My desktop while working on Ronin. Half of the screen is used by Ronin itself, while the other half is used by tutorials and documentation.

There’s something fascinating about creating art by simply specifying a set of rules for the computer. There are so many possibilities! I’m hoping that I’ll continue exploring generative art for the years to come. I’ve been collecting my favorite works in https://jagtalon.com/generative-art/ as well so check that out from time to time if you’re interested!

Going from Browser to Paper

Prints of my art that looks like a fingerprint that I just took out of the box.

I recently had some of my generative art printed, and I’m stoked to finally have them in my hands! It feels surreal to see my creative coding projects on my wall, taking up space in the physical world instead of being mere pixels on the screen.

It’s surprisingly straightforward and affordable. I first adjusted <canvas> to be 3600Γ—5400 pixels or 12Γ—18 inches at 300 dpi. Whenever I see a piece that I like, canvas-sketch lets me quickly export the image by pressing Ctrl-S.

I didn’t know where to get it printed at first, so I had one printed at Staples. Unfortunately, the colors looked a bit dull, and they weren’t as vivid as I had hoped. It was also $10 a page, so it was a bit expensive. Fortunately, a friend of mine told me about a shop right here in Philadelphia called Fireball Printing.

They have a minimum of 5 pages per print job, but I was surprised that it only cost me $3.70 for all 5 prints! The colors also looked unbelievably accurate to me.

I’ve been hoping to sell physical prints on Etsy, but right now, I’m uncomfortable with picking up, packing, and mailing art when there’s a pandemic. So, for now, I have a πŸ› digital-only shop. Check it out!

Creative Coding: Making Noise

A sample of the noise art that I've been experimenting with. It looks a bit fuzzy and fur-like.

I love the wave-like patterns in these images. I recently made these using <canvas> (which I’m learning about in the Creative Coding workshop that I’m taking), and each shape that you see is a Unicode character.

Their positions are evenly distributed on a grid while their sizes and rotations are generated using the noise2D function. I played around with the different variables (rotation, frequency, amplitude, size, and the number of elements), and it made these wonderful works of art.

I’d love to be able to print some of these so that I could hang them up on my wall.

Creative Coding: Setting Up on Windows

A screenshot showing Windows Terminal

The Canvas and WebGL workshop that I’m taking right now is taught using macOS, so the course assumes that I can access some Unix tools and commands in the dev environment. Since Windows isn’t built on top of BSD or Linux, I have to do a bit more work to get up and running.

Install Windows Subsystem for Linux

Windows Subsystem for Linux or WSL is the best way to get a Linux environment running on Windows. It’s a lightweight virtual machine that runs unmodified Linux binaries on top of Windows. It’s so fast that it doesn’t feel like I’m using a VM at all.

See how quickly WSL boots up. It’s magic.

There are two versions of WSL, so I made sure to get WSL 2 because it’s 2-5x faster when it comes to IO operations like git clone and npm installβ€”commands that I’ll often be using!

Install Remote – WSL Extension on VSCode

The Remote – WSL extension on VSCode forces all the commands to run in the Linux VM. It makes sure that I’m interacting with Linux all the time while I’m in VSCode. So even though the editor is running on Windows, programs like Git or Node are all running in Linux.

VSCode with the Remote – WSL extension.

Bonus: Install Windows Terminal

I’m a fan of good-looking terminals, and the built-in terminal on macOS is beautiful. It looks modern, and it supports tabs and theme customization. The built-in Command Prompt on Windows, on the other hand, looks quite ancient.

Fortunately, Windows Terminal is available in the Microsoft Store, and it supports tabs, vertical splitting, and even emojis. I don’t know why this isn’t included in the OS in the first place!

Windows Terminal with vertical splitting.

Hello, Creative Coding

Now that I’m a full-time designer, most of my days are either spent planning projects in Asana or working on them on Figma. I hardly ever do any programming nowadays, and I miss the feeling of writing code and bringing websites to life.

I’ve been thinking about small programming projects that I could do in my spare time, and I recently ran into a creative coding course on Frontend Masters. I’ve spent a lot of time making websites and creating user interfaces, but I never thought about using programming to create art. The visual aspect of it is enticing, and I love the fact that it’s can be a creative outlet for me.

I’m early in the course, and right now, I’m going through the Canvas API. We’re on the topic of creating grids at the moment, and I’m excited about the idea of creating digital art that I can actually hang on the wall.

I’m enjoying it so far, and I’m thrilled to continue making art through code. I’ll make an effort to blog as I go through the course!