Generative Art for Website Backgrounds
Since my personal website Semicolon Software doesn't need to contain much more than a few links into different places on the web, I wanted to make it more interesting by doing some JavaScript experimentation. The result of this is a beautiful piece of randomly generated background art every time that you reload the page!
This article is a brief summary of the techniques used to create this background.
Dependencies
The website is written in ES2015 and cross-compiled into today's EcmaScript using babel. Drawing operations are performed using svg.js. chroma.js is used for color manipulations and the built-in support for the ColorBrewer palettes.
How it's made
The generated backgrounds consist of two parts, both randomly selected: A color palette and a randomly generated pattern. We'll first discuss the two currently implemented pattern algorithms and then talk about how to randomly generate color palettes.
Generating Patterns
Triangulation
This pattern is heavily inspired by the Trianglify package by Quinn Rohlf although I've implemented this myself, making some of my own choices in the process.
To start out, we generate a square grid of varying pixel size between 150-200px:
We then shift all grid points by a random offset of ±30% of the grid size in both dimensions:
Finally, every quadrilateral cell on this grid is split into two triangles:
We map color onto the grid points by defining separate color scales for the X and Y dimensions, determining a color according to the X and Y coordinates separately, and then mixing the two colors using chroma.mix
.
Contour Lines
This pattern is a mixture of two well-known algorithms, Simplex Noise to generate a 2D field of heights and Marching Squares to translate the 2D field into a set of isocontour polygons.
Simplex Noise
Simplex noise is an improved version of Perlin Noise also invented by Ken Perlin that can generate random cloudy shapes in any number of dimensions. I use noise.js by Stefan Gustavson and Joseph Gentle to generate a coarse-grained grid of Simplex Noise points:
Image taken from https://code.google.com/p/fractalterraingeneration/wiki/Simplex_Noise
Marching Squares
Next on our workflow is the Marching Squares Algorithm that is used to translate the grid of noise values into iso-contour polygons. I created my own implementation for both Marching Squares and a subsequent edge joining step to merge the individual edges into polygons[1].
Image credit: Bananenfalter on Wikimedia Commons
We repeat this for several isocontour levels that will be mapped to different levels of the color palette.
Generating Color Palettes
There are many semi-automatic color palette generators on the internet that typically work by choosing a point on the color wheel and then deriving points at different angles from the original point (and possibly modifying saturation and brightness) to generate a color palette.
I've implemented three strategies for choosing pleasing color scales to paint the previously described patterns with. One of them is picked at random every time the page is loaded.
Analogous Colors
First, we simply choose a random hue and a complimentary color that is on the opposite site of the color wheel. We then use chroma.scale initializing it with both the original random and its complementary at 50% saturation and lightness with a hsl
interpolation mode to generate a pleasing color scale.
Neighboring Colors
Alternatively, we choose a random hue from the color wheel and then offset that hue by ±45° to derive two neighboring hues. Again, we use chroma.scale and initialize it with a gradient going from left-neighbor → random-color → right-neighbor.
ColorBrewer Colors
Finally, we can also just randomly choose a palette from the beautiful ColorBrewer2 palette library.
Conclusion
By having several random components that can be mixed together freely, the method described in this article can generate many interesting-looking backgrounds for my personal webpage. Check the results out yourself and see which ones you like best by refreshing the page!
See also
Contact me if you are curious about my implementation of Marching Squares. ↩︎