The Zerofox Syndicate

A Canvas Background Animation

2020-05-22

Here is some code for a simple background animation created with 2d canvas.

How to create an animated background

First add this piece of HTML.

<canvas id="bg"></canvas>

Then write the rest of the required Javascript.

const canvas = document.getElementById("bg");
const c = canvas.getContext("2d");
const radius = 4;
const connDistance = 150;
const maxSpeed = 0.20;
const dotColor = "#444";
const dotDensityFactor = 30; // about the nr dots for a 720 screen

let dotAmount;
let dots = [];

function init() {
    canvas.style = "position:fixed;top:0;left:0;width:100%;height:100%;" +
        "z-index:-10;"
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    dotAmount = Math.floor((window.innerWidth * window.innerHeight / 855000) 
        * dotDensityFactor)
    dots = Array.apply(null, Array(dotAmount)).map(function() {
        return [
            (canvas.width - 2 * radius) * Math.random() + radius,  // x
            (canvas.height - 2 * radius) * Math.random() + radius, // y
            (maxSpeed * 2 * Math.random()) - maxSpeed,
            (maxSpeed * 2 * Math.random()) - maxSpeed
        ];
    });
}

function resize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    dotAmount = Math.floor((window.innerWidth * window.innerHeight / 855000) 
        * dotDensityFactor)
                   

    if (dots.length < dotAmount) {
        const diff = dotAmount - dots.length;
        dots = dots.concat(Array.apply(null, Array(diff)).map(function() {
                return [
                    // x
                    (canvas.width - 2 * radius) * Math.random() + radius,
                    // y
                    (canvas.height - 2 * radius) * Math.random() + radius,
                    (maxSpeed * 2 * Math.random()) - maxSpeed,
                    (maxSpeed * 2 * Math.random()) - maxSpeed
                ];
            })
        );
    } else {
        dots.length = dotAmount
    }
}

function getDistance(p1, p2) {
    // C² = A² + B²
    return Math.sqrt(Math.pow(Math.abs(p1[0] - p2[0]), 2) + 
           Math.pow(Math.abs(p1[1] - p2[1]), 2));
}

function animate() {
    requestAnimationFrame(animate);
    c.clearRect(0, 0, innerWidth, innerHeight);
    dots.forEach((d, i, arr) => {
        c.beginPath();
        c.arc(d[0], d[1], radius, Math.PI * 2, false);
        c.strokeStyle = 'rgba(0, 0, 0, 0)';
        c.fillStyle = dotColor;
        c.fill();
        c.stroke();
        arr.forEach(d2 => {
            const distance = getDistance(d, d2);
            if (distance < connDistance && distance > 1) {
                c.beginPath();
                c.moveTo(d[0], d[1]);
                c.lineTo(d2[0], d2[1]);
                c.lineWidth = 8;
                c.strokeStyle = dotColor;
                c.stroke();

                c.beginPath();
                c.moveTo(d[0], d[1]);
                c.lineTo(d2[0], d2[1]);
                c.lineWidth = 2;
                c.strokeStyle = 'rgba(255, 255, 255, 1)';
                c.stroke();
            }
        });
    });

    dots.forEach((d, i, arr) => {
        arr[i][1] += d[3];

        // Handle border collisions
        if (arr[i][0] < (0 + radius)) { arr[i][2] = Math.abs(d[2]) }

        if (arr[i][1] < (0 + radius)) { arr[i][3] = Math.abs(d[3]) }

        if (arr[i][0] > (innerWidth - radius)) {
            arr[i][2] = 0 - Math.abs(d[2])
        }

        if (arr[i][1] > (innerHeight - radius)) {
            arr[i][3] = 0 - Math.abs(d[3])
        }
    })
}

window.addEventListener('resize', resize);
window.addEventListener('DOMContentLoaded', init);
animate();

Conclusion

Originally I wanted to create a step-by-step guide with little example canvases displaying the intermediate steps towards creating the full animation. This however quickly became a complete mess. The example code had to be escaped between the intermediate canvas code, which was confusing and I also had to modify all the intermediate canvas code not to conflict with the real running code, but this meant I couldn’t be sure anymore that my example code was correct.

So I decided to just upload it as is. Now it is basically a version of the draw the rest of the fucking owl meme.

draw the rest of the fucking owl meme image

Tags: javascript