Will McLean
Process diary

Colour grid

Last modified: October 27, 2018
Created: October 7, 2018


This is an exercise by Will McLean. View this exercise here or view all exercises here.

Overview

I needed a way to generate visuals to go with short articles on code I write on my website. Previously, I had made very quick compositions in Photoshop. However, as I was writing my knowledge base articles on the fly (whilst in mid development, on the train and in the park) the fact that I had to go home, create an image and then publish was starting to annoy me. I had been reading Generative Design, Visualize, Program, and Create with Processing by Hartmut Bohnacker, Benedikt Groß, Julia Laub and Claudius Lazzeroni (editor). This book has working examples of generative design techniques written in Processing. I decided to use one of their examples to solve my problem. If the example could be rewritten in a browser friendly language I could have a site that generated the artwork. When writing my knowledge base all I would have to do is visit the url, refresh the page and screenshot the image. Voila!

The example

The authors introduce the example Colour Palettes from rules like so:

“All colours are made up of three components: hue, saturation, and brightness. The values for these colour components are defined using a set of rules. By using controlled random functions, you can quickly create different palettes in specific colour nuances”
(Generative Design, Visualize, Program, and Create with Processing, pg. 194)

This is one of the less complex exercises from the book and yet it is very effective in generating visuals for my purpose. I am very interested in the concept of randomness within restrictions or “controlled randomness” as a way of delivering interesting design within the commercial setting. That such a simple piece of code can deliver such varied and interesting results is a real eye opener. The future is here!

Adapting the example

The example is written in Processing so I just needed to adapt this to pure js, html (and php) and css.

I fill the screen with 1000 blocks. These will form my grid.

<div class="container">
    <?php for ( $x = 1; $x < 1000; $x++ ): ?>
        <div class="block"></div>
    <?php endfor; ?>
</div>

The size of these blocks is based on the mouse position. So any time the mouse moves we need to update the size of each block.

let blocks = document.querySelectorAll( '.block' );

function mouseMoveHandler( event ) {
    for ( let i = 0; i < blocks.length; i++ ) {
        blocks[ i ].style.width = event.clientX + 'px';
        blocks[ i ].style.height = event.clientY + 'px';
    }
}

window.addEventListener( 'mousemove', mouseMoveHandler );

I initially decided on three colour “types”. One with no limits (ie. anywhere on the HSL spectrum), one that was pale (desaturated and light) and one that was muddy (desaturated and dark). I created functions to generate these colours.

function getColour(){
    let hue = Math.random() * 360,
        sat = Math.random() * 100,
        lum = Math.random() * 100;
    return 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
}

function getPaleColour(){
    let hue = Math.random() * 360,
        sat = Math.random() * 30,
        lum = Math.random() * 40 + 60;
    return 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
}

function getMuddyColour(){
    let hue = Math.random() * 360,
        sat = Math.random() * 30,
        lum = Math.random() * 40;
    return 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
}

I then created 6 options with which to colour the blocks. The first three coloured the blocks using exclusively pale, muddy or unlimited colour types. The last three options coloured the blocks alternately using two of the colour types.

function setColours() {

    let option = Math.floor( Math.random() * 7 );

    switch ( option ) {
        // Option 1 - No limits.
        case 1:
            for ( let i = 0; i < blocks.length; i++ ) {
                blocks[ i ].style.backgroundColor = getColour();
            }
            break;
        // Option 2 - Pale
        case 2:
            for ( let i = 0; i < blocks.length; i++ ) {
                blocks[ i ].style.backgroundColor = getPaleColour();
            }
            break;
        // Option 3 - Muddy
        case 3:
            for ( let i = 0; i < blocks.length; i++ ) {
                blocks[ i ].style.backgroundColor = getMuddyColour();
            }
            break;
        // Option 4 - Alternate. Pale/Muddy
        case 4:
            for ( let i = 0; i < blocks.length; i++ ) {
                let hue, sat, lum;
                if ( i % 2 ) {
                    blocks[ i ].style.backgroundColor = getMuddyColour();
                } else {
                    blocks[ i ].style.backgroundColor = getPaleColour();
                }
                blocks[ i ].style.backgroundColor = 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
            }
            break;
        // Option 5 - Alternate. Pale/no limits
        case 5:
            for ( let i = 0; i < blocks.length; i++ ) {
                let hue, sat, lum;
                if ( i % 2 ) {
                    blocks[ i ].style.backgroundColor = getColour();
                } else {
                    blocks[ i ].style.backgroundColor = getPaleColour();
                }
            }
            break;
        // Option 6 - Alternate. Muddy/no limits
        case 6:
            for ( let i = 0; i < blocks.length; i++ ) {
                let hue, sat, lum;
                if ( i % 2 ) {
                    blocks[ i ].style.backgroundColor = getColour();
                } else {
                    blocks[ i ].style.backgroundColor = getMuddyColour();
                }
            }
            break;
    }


}

setColours();
window.addEventListener( 'click', setColours );

I later decided to add three more colour types as options. These three were limited by hue so the resulting colours turned out red(ish), green(ish) and blue(ish).

function getRedColour(){
    let hue = Math.random() * 120 + 240,
        sat = Math.random() * 100,
        lum = Math.random() * 100;
    return 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
}

function getGreenColour(){
    let hue = Math.random() * 120,
        sat = Math.random() * 100,
        lum = Math.random() * 100;
    return 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
}

function getBlueColour(){
    let hue = Math.random() * 120 + 120,
        sat = Math.random() * 100,
        lum = Math.random() * 100;
    return 'hsla(' + hue + ',' + sat + '%,' + lum + '%,1)';
}

Extending it

How can we extend it? OMG it is so easy. We can add something as simple as:

.block:nth-child(odd) {
    transform: rotateZ(-10deg);
}
.block:nth-child(even) {
    transform: rotateZ(10deg);
}

And this will generate wildly varied results. The hard part now is deciding on what small variation I want to use? 🤔

Credits:

Concept: Hartmut Bohnacker, Benedikt Groß & Julia Laub

This is a Exercises post.