<!-- CLICK TO GENERATE -->

<canvas id="loadingScreen"></canvas>

:root {
    --bgColor:#ffffff;
}

body {
  margin: 0;
}


@media (prefers-color-scheme: dark) {
    :root {
        --bgColor:#282525;
    }
}
import Knobs from "https://cdn.skypack.dev/@yaireo/knobs@1.3.5";

let cellSize = 40;
const colours = ['#ff318c', '#b345f1', '#765af8'];
const shapes = ['spot', 'crossSpots', 'quarterCircles'];
const circleQuarters = [
    'topRight',
    'bottomRight',
    'bottomLeft',
    'topLeft'
];
let spotRadius = cellSize / 8;
const canvas = document.getElementById('loadingScreen');
const ctx = canvas.getContext('2d');
let bgColour = getComputedStyle(document.documentElement).getPropertyValue('--bgColor');

let quarterCount = 5;

stretchCanvasToWindow();
draw();

const knobs = new Knobs({
  knobs: [
    {
      label: 'Cell Size',
      type: 'range',
      value: 40,
      min: 10,
      max: 200,
      onChange: (e, knobData, hsla) => {
        cellSize = parseInt(knobData.value);
        spotRadius = cellSize / 8;
         draw();
      },    
    },
    {
      label: 'Quarter Count',
      type: 'number',
      value: 5,
      min: 1,
      max: 50,
      onChange: (e, knobData, hsla) => {
        quarterCount = parseInt(knobData.value);
        draw();
      },
    },
    {
      label: 'Background Colour',
      cssVarsHSLA: false,
      type: 'color',
      value: bgColour,
      defaultFormat: 'hex',
      onChange: (e, knobData, hsla) => {
        bgColour = removeHexAlpha(knobData.value);
        draw();
      },
    },
    {
      label: 'Shape Colour 1',
      type: 'color',
      value: '#ff318c',
      defaultFormat: 'hex',
      onChange: (e, knobData, hsla) => {
        colours[0] = removeHexAlpha(knobData.value);
        draw();
      },
    },
    {
      label: 'Shape Colour 2',
      type: 'color',
      value: '#b345f1',
      defaultFormat: 'hex',
      onChange: (e, knobData, hsla) => {
        colours[1] = removeHexAlpha(knobData.value);
        draw();
      },
    },
    {
      label: 'Shape Colour 3',
      type: 'color',
      value: '#765af8',
      defaultFormat: 'hex',
      onChange: (e, knobData, hsla) => {
        colours[2] = removeHexAlpha(knobData.value);
        draw();
      },
    },
  ]
});

window.addEventListener('resize', (e) => {
    stretchCanvasToWindow();
    draw();
});

canvas.addEventListener('click', draw);

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
    bgColour = getComputedStyle(document.documentElement).getPropertyValue('--bgColor');
    draw();
});

function draw() {
    for (let x = 0; x < canvas.width; x+= cellSize) {
        for (let y = 0; y < canvas.height; y+= cellSize) {
            const shapeChoice = randomShape();

            switch(shapeChoice) {
                case 'spot':
                    spot(x, y);
                    break;
                case 'crossSpots':
                    crossSpots(x, y);
                    break;
                case 'quarterCircles':
                    quarterCircles(x, y);
                    break;
            }
        }
    }
}

function spot(x, y) {
    const cellCentre = cellCentreCoordinates(x, y);
    ctx.fillStyle = randomColour();
    ctx.fillRect(x, y, cellSize, cellSize);
    ctx.fillStyle = bgColour;
    circle(cellCentre.x, cellCentre.y, spotRadius);
    ctx.fill();
}

function crossSpots(x, y) {
    const cellCentre = cellCentreCoordinates(x, y);
    const spots = crossSpotCoordinates(cellCentre.x, cellCentre.y);

    ctx.fillStyle = bgColour;
    ctx.fillRect(x, y, cellSize, cellSize);
    ctx.fillStyle = randomColour();

    spots.forEach((spot) => {
        circle(spot.x, spot.y, spotRadius);
        ctx.fill();
    });
}

function crossSpotCoordinates(cX, cY) {
    const centreOffSet = cellSize / 4;
    return [
        // Top
        xAndYCoordinates(cX, cY - centreOffSet),
        // Right
        xAndYCoordinates(cX + centreOffSet, cY),
        // Bottom
        xAndYCoordinates(cX, cY + centreOffSet),
        // Left
        xAndYCoordinates(cX - centreOffSet, cY),
    ]
}

function cellCentreCoordinates(cX, cY) {
    return xAndYCoordinates(
        cX + (cellSize / 2),
        cY + (cellSize / 2)
    );
}

function xAndYCoordinates(x, y) {
    return {
        x: x,
        y: y
    };
}

function quarterCircles(x, y) {
    const cellCorner = randomCellCorner();
    const quarterColour = randomColour();
    const quarterCircleParams = decideQuarterCircleParamValues(cellCorner, x, y);

    ctx.fillStyle = bgColour;
    ctx.fillRect(x, y, cellSize, cellSize);
    ctx.fillStyle = quarterColour;

    let radiusIncrement = cellSize / quarterCount;
    let runningRadius = cellSize;

    for (let i = 0; i < quarterCount; i++) {
        let fillStyle = quarterColour;

        if (i % 2 === 1) {
            fillStyle = bgColour;
        }

        drawQuarterCircle (
            quarterCircleParams.centreX,
            quarterCircleParams.centreY,
            runningRadius,
            quarterCircleParams.startAngle,
            fillStyle
        );

        runningRadius -= radiusIncrement;
    }
}

function circle(cX, cY, radius) {
    ctx.beginPath();
    ctx.moveTo(cX, cY);
    ctx.arc(cX, cY, radius, 0, Math.PI * 2);
    ctx.closePath();
}

function drawQuarterCircle (cX, cY, radius, startAngleDeg, fillStyle) {
    const startAngle = startAngleDeg * (Math.PI / 180);
    const endAngle = startAngle + Math.PI * 0.5;

    ctx.fillStyle = fillStyle;
    ctx.beginPath();
    ctx.moveTo(cX, cY);
    // Draw actual arc
    ctx.arc(cX, cY, radius, startAngle, endAngle, false);
    ctx.closePath()
    ctx.fill();
}

function randomShape() {
    return shapes[randomIndex(shapes.length)];
}

function randomColour() {
    return colours[randomIndex(colours.length)];
}

function randomCellCorner() {
    return circleQuarters[randomIndex(circleQuarters.length)];
}

function randomIndex(arrayLength) {
    return Math.floor(Math.random() * arrayLength);
}

function decideQuarterCircleParamValues(cellCorner, x, y) {
    let centreX, centreY, startAngle, endAngle;

    switch (cellCorner) {
        case 'topRight':
            centreX = x + cellSize;
            centreY = y;
            startAngle = 90;
            break;
        case 'bottomRight':
            centreX = x + cellSize;
            centreY = y + cellSize;
            startAngle = 180;
            break;
        case 'bottomLeft':
            centreX = x;
            centreY = y + cellSize;
            startAngle = 270;
            break;
        case 'topLeft':
            centreX = x;
            centreY = y;
            startAngle = 0;
            break;
    }

    return {
        centreX: centreX,
        centreY: centreY,
        startAngle: startAngle
    };
}

function stretchCanvasToWindow() {
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
}

function removeHexAlpha(hex) {
  return hex.slice(0, 7);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.