<head>
    <link rel="stylesheet" href="../../css/system.css">
    <link rel="stylesheet" href="../../css/typography.css">
    <link rel="stylesheet" href="../../css/variables.css">
    <link rel="stylesheet" href="../../css/inputs.css">
    <link rel="stylesheet" href="../../css/button.css">
    <link rel="stylesheet" href="../../css/callouts.css">
    <link rel="stylesheet" href="../../css/switch.css">

    <style>
        :root {
            --bg-inner: white;
            --bg-outer: white;
        }

        * {
            box-sizing: border-box;
        }

        @font-face {
            font-family: Campton;
            src: url(https://f.hubspotusercontent20.net/hubfs/260128/Landing%20Page%20Files/Images/Fonts/campton-bold.otf);
        }

        body {
            position: relative;
            font-family: Campton;
        }

        .controls {
            display: flex;
            width: fit-content;
            gap: 1.5em;
            margin-left: 1.5em;
        }

        .container {
            height: 95vh;
            width: 95vw;
            padding: 1rem;
            --color-one: #57585a;
            --color-two: #fff;
            --color-three: #f0f1f4;
            --color-four: #d6d8da;
            --color-five: #939496;
        }

        .container svg text {
            font-family: Campton !important;
        }

        .container svg {
            width: 100%;
            aspect-ratio: 1;
        }

        :has(.switch input:nth-of-type(4):checked) .container {
            --color-one: #003c71;
            --color-two: #1968a1;
            --color-three: #2e85be;
            --color-four: #66a6ce;
            --color-five: #b8d8ea;
        }

        :has(.switch input:nth-of-type(3):checked) .container {
            --color-one: #582C83;
            --color-two: #D3BFE3;
            --color-three: #663491;
            --color-four: #8246AF;
            --color-five: #B794D1;
        }

        :has(.switch input:nth-of-type(2):checked) .container {
            --color-one: #1B6500;
            --color-two: #5F9A00;
            --color-three: #84BD00;
            --color-four: #ABD064;
            --color-five: #DCEBBD;
        }

        :has(.switch input:nth-of-type(1):checked) .container {
            --color-one: #F57D00;
            --color-two: #FF9800;
            --color-three: #FFB300;
            --color-four: #FEC10D;
            --color-five: #FED650;
        }

        .container svg * {
            /*    Removes little gaps between the shapes */
            shape-rendering: crispEdges;
        }

        .button {
            background: #582C83;
            color: white;
            border-radius: 0.3em;
            padding: .3em 1.33em;
            box-sizing: border-box;
            display: inline-flex;
            align-items: center;
            gap: .5em;
            margin: .25em;
        }

        .DLbutton {
            border: 2px solid #582C83;
            color: #582C83;
            border-radius: 0.3em;
            padding: .3em 1.33em;
            box-sizing: border-box;
            display: inline-flex;
            align-items: center;
            gap: .5em;
            margin: .25em;
            text-decoration: none;
        }

        .button svg {
            width: 1.25rem;
            transition: 0.3s ease-in-out transform;
        }

        .button:hover svg {
            transform: rotate(-45deg);
        }

        .button:focus,
        .button:active {
            outline: 2px solid #f06;
        }

        .button:focus svg,
        .button:active svg {
            transform: rotate(-90deg);
        }

        .switch {
            display: flex;
            align-items: center;
            position: relative;
            height: 2em;
            background: color-mix(in srgb, var(--accent-color) 10%, white);
            border-radius: 1em;
            outline: 4px solid var(--accent-color);
            overflow: hidden;
            transition: background, outline 0.3s;
        }

        .switch label {
            font-weight: bold;
            position: relative;
            z-index: 2;
            margin: 0 auto;
            width: 120px;
            line-height: 32px;
            font-size: 18px;
            color: #393a3b;
            text-align: center;
            cursor: pointer;
        }

        .switch input {
            display: none;
        }

        .switch input:checked+label {
            color: #fff;
            transition: 0.15s ease-out;
            transition-property: color, background-color, outline;
        }

        :has(.switch input:nth-of-type(1):checked) {
            --accent-color: #ff9800;
        }

        :has(.switch input:nth-of-type(2):checked) {
            --accent-color: #84bd00;
        }

        :has(.switch input:nth-of-type(3):checked) {
            --accent-color: #582c83;
        }

        :has(.switch input:nth-of-type(4):checked) {
            --accent-color: #003c71;
        }

        :has(.switch input:nth-of-type(5):checked) {
            --accent-color: #393a3b;
        }

        .switch input:checked+label:nth-of-type(1),
        .switch input:checked+label:nth-of-type(2) {
            color: #393a3b;
        }

        .switch input:checked+label~.switch-selector {
            background-color: var(--accent-color);
        }

        .switch input:checked+label:nth-of-type(1)~.switch-selector {
            --translate: 0%;
        }

        .switch input:checked+label:nth-of-type(2)~.switch-selector {
            --translate: 100%;
        }

        .switch input:checked+label:nth-of-type(3)~.switch-selector {
            --translate: 200%;
        }

        .switch input:checked+label:nth-of-type(4)~.switch-selector {
            --translate: 300%;
        }

        .switch .switch-selector {
            position: absolute;
            z-index: 1;
            top: 0px;
            left: 0px;
            display: block;
            width: 120px;
            height: 2em;
            border-radius: 1em;
            transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
            transform: translateX(var(--translate));
        }

        @media only screen and (max-width: 676px) {
            .switch {
                justify-content: flex-start;
                flex-flow: row wrap;
                width: 120px;
                height: 10em;
            }

            .switch .switch-selector {
                transform: translateY(var(--translate));
            }
        }
    </style>
</head>

<body>
    <div class="controls">
        <div class="switch">
            <input id="switch-first" name="toggle" type="radio" checked />
            <label for="switch-first">Orange</label>
            <input id="switch-second" name="toggle" type="radio" />
            <label for="switch-second">Green</label>
            <input id="switch-third" name="toggle" type="radio" />
            <label for="switch-third">Purple</label>
            <input id="switch-forth" name="toggle" type="radio" />
            <label for="switch-forth">Blue</label>
            <input id="switch-fifth" name="toggle" type="radio" />
            <label for="switch-fifth">Grey</label>
            <span class="switch-selector"></span>
        </div>
        <button class="button" aria-label="Regenerate" type="button"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
            </svg> <span>Regenerate</span></button>

        <a id="test" target="_blank" class="DLbutton" download>Download vector</a>
    </div>
    <div class="container"></div>
    <span id="downloadContainer"></span>
    <script type="module">
        import {
            SVG
        } from "https://cdn.skypack.dev/@svgdotjs/svg.js@3.1.1";
        import {
            random
        } from "https://cdn.skypack.dev/@georgedoescode/generative-utils@1.0.37";
        import tinycolor from "https://cdn.skypack.dev/tinycolor2@1.4.2";
        import gsap from "https://cdn.skypack.dev/gsap@3.9.1";
        console.clear();
        let draw, squareSize, numRows, numCols, colors, colorPalette;
        const selectedCharacters = ["&"];
        colors = [
            [
                "var(--color-one)",
                "var(--color-two)",
                "var(--color-three)",
                "var(--color-four)",
                "var(--color-five)"
            ]
        ];
        /*colors = [
        ["#57585A","#fff","#F0F1F4","#D6D8DA","#939496"],
        ["#582C83","#D3BFE3","#663491","#8246AF","#B794D1"],
        ["#F57D00","#FF9800","#FFB300","#FEC10D","#FED650"],
        ["#1B6500","#5F9A00","#84BD00","#ABD064","#DCEBBD"],
        ["#003C71","#1968A1","#2E85BE","#66A6CE","#B8D8EA"],
        ];*/
        /*
        Block Design Functions
        */
        function drawCircle(x, y, foreground, background) {
            // Create group element
            const group = draw.group().addClass("draw-circle");
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            // Draw Foreground
            group.circle(squareSize).fill(foreground).move(x, y);
            // 30% of the time add inner circle
            if (Math.random() < 0.3) {
                group
                    .circle(squareSize / 2)
                    .fill(background)
                    .move(x + squareSize / 4, y + squareSize / 4);
            }
        }

        function drawDots(x, y, foreground, background) {
            const group = draw.group().addClass("dots");
            const sizeOptions = [2, 3, 4];
            const size = random(sizeOptions);
            const offset = 10;
            const circleSize = 10;
            const space = (squareSize - offset * 2 - circleSize) / (size - 1);
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            // Draw Dots
            for (let i = 0; i < size; i++) {
                for (let j = 0; j < size; j++) {
                    group
                        .circle(circleSize)
                        .fill(foreground)
                        .move(x + offset + i * space, y + offset + j * space);
                }
            }
        }

        function drawCross(x, y, foreground, background) {
            const group = draw.group().addClass("draw-cross");
            const crossGroup = draw.group();
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            // Draw Foreground
            crossGroup
                .rect(squareSize / 1.5, squareSize / 5)
                .fill(foreground)
                .center(x + squareSize / 2, y + squareSize / 2);
            crossGroup
                .rect(squareSize / 1.5, squareSize / 5)
                .fill(foreground)
                .center(x + squareSize / 2, y + squareSize / 2)
                .transform({
                    rotate: 90
                });
            if (Math.random() < 0.4) {
                crossGroup.transform({
                    rotate: 45,
                    origin: "center center"
                });
            }
        }

        function drawOppositeCircles(x, y, foreground, background) {
            const group = draw.group().addClass("opposite-circles");
            const circleGroup = draw.group();
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            const mask = draw.rect(squareSize, squareSize).fill("#fff").move(x, y);
            const offset = random([
                [0, 0, squareSize, squareSize],
                [0, squareSize, squareSize, 0]
            ]);
            // Draw Foreground
            circleGroup
                .circle(squareSize)
                .fill(foreground)
                .center(x + offset[0], y + offset[1]);
            circleGroup
                .circle(squareSize)
                .fill(foreground)
                .center(x + offset[2], y + offset[3]);
            circleGroup.maskWith(mask);
            group.add(circleGroup);
        }

        function drawQuarterCircle(x, y, foreground, background) {
            const group = draw.group().addClass("quarter-circle");
            const circleGroup = draw.group();
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            const mask = draw.rect(squareSize, squareSize).fill("#fff").move(x, y);
            const xOffset = squareSize * random([0, 1], true);
            const yOffset = squareSize * random([0, 1], true);
            // Draw Foreground
            circleGroup
                .circle(squareSize * 2)
                .fill(foreground)
                .center(x + xOffset, y + yOffset);
            if (Math.random() < 0.6) {
                circleGroup
                    .circle(squareSize)
                    .fill(background)
                    .center(x + xOffset, y + yOffset);
            }
            circleGroup.maskWith(mask);
            group.add(circleGroup);
        }

        function drawDiagonalSquare(x, y, foreground, background) {
            const group = draw.group().addClass("diagonal-square");
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            // Draw Foreground
            let polygon;
            if (Math.random() > 0.5) {
                polygon = group.polygon(
                    `${x},${y} ${x},${y + squareSize}, ${x + squareSize},${y}`
                );
            } else {
                polygon = group.polygon(
                    `${x},${y} ${x + squareSize},${y} ${x + squareSize},${y + squareSize}`
                );
            }
            polygon.fill(foreground);
        }

        function drawLetterBlock(x, y, foreground, background) {
            const group = draw.group().addClass("half-square");
            const mask = draw.rect(squareSize, squareSize).fill("#fff").move(x, y);
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            // Draw Foreground
            const character = random(selectedCharacters);
            const text = group.plain(character);
            text.font({
                family: "Campton",
                size: squareSize * 1.3,
                weight: 800,
                anchor: "center",
                fill: foreground,
                leading: 1
            });
            text.center(x + squareSize / 2, y + squareSize / 2);
            group.maskWith(mask);
        }

        function drawHalfSquare(x, y, foreground, background) {
            const group = draw.group().addClass("half-square");
            let halfX = 2;
            let halfY = 2;
            if (random([0, 1])) {
                halfX = 1;
            } else {
                halfY = 1;
            }
            // Draw Background
            group.rect(squareSize, squareSize).fill(background).move(x, y);
            // Draw Foreground
            group
                .rect(squareSize / halfX, squareSize / halfY)
                .fill(foreground)
                .move(x, y);
        }
        /*
        Create New Piece
        */
        function generateNewGrid() {
            // Fade out SVG
            gsap.to(".container > svg", {
                opacity: 0,
                scale: 0.8,
                duration: 0.25,
                onComplete: () => {
                    // Remove previous SVG from DOM
                    document.querySelector(".container").innerHTML = "";
                    // Start new SVG creation
                    drawGrid();
                }
            });
        }
        async function drawGrid() {
            // Set Random Palette
            colorPalette = random(colors);
            // Set Variables
            squareSize = 100;
            numRows = random(4, 8, true);
            numCols = random(4, 8, true);
            // Create parent SVG
            draw = SVG()
                .addTo(".container")
                .size("100%", "100%")
                .viewbox(`0 0 ${numRows * squareSize} ${numCols * squareSize}`)
                .opacity(0);
            // Create Grid
            for (let i = 0; i < numRows; i++) {
                for (let j = 0; j < numCols; j++) {
                    generateLittleBlock(i, j);
                }
            }
            generateBigBlock();
            gsap.fromTo(
                ".container > svg", {
                    opacity: 0,
                    scale: 0.8
                }, {
                    opacity: 1,
                    scale: 1,
                    duration: 0.4,
                    ease: "back.out(1.7)"
                }
            );
            encode_as_img_and_link();
        }
        /*
        Utility Functions
        */
        function generateLittleBlock(i, j) {
            const {
                foreground,
                background
            } = getTwoColors(colorPalette);
            const blockStyleOptions = [
                drawDots,
                drawHalfSquare,
                drawDiagonalSquare,
                drawCircle,
                drawOppositeCircles,
                drawQuarterCircle,
                drawLetterBlock
            ];
            const blockStyle = random(blockStyleOptions);
            const xPos = i * squareSize;
            const yPos = j * squareSize;
            blockStyle(xPos, yPos, foreground, background);
        }

        function generateBigBlock() {
            const {
                foreground,
                background
            } = getTwoColors(colorPalette);
            const blockStyleOptions = [
                //drawHalfSquare,
                //drawDiagonalSquare,
                //drawCircle,
                //drawQuarterCircle,
                //drawOppositeCircles,
                drawLetterBlock
            ];
            let prevSquareSize = squareSize;
            // Random multiplier (2 or 3 squares)
            const multiplier = random([2, 3]);
            // Random X position
            const xPos = random(0, numRows - multiplier, true) * prevSquareSize;
            // Random Y position
            const yPos = random(0, numCols - multiplier, true) * prevSquareSize;
            // Make squareSize bigger
            squareSize = multiplier * 100;
            // Get random square style
            const blockStyle = random(blockStyleOptions);
            blockStyle(xPos, yPos, foreground, background);
            // Reset squareSize
            squareSize = prevSquareSize;
        }

        function getTwoColors(colors) {
            let colorList = [...colors];
            // Get random index for this array of colors
            const colorIndex = random(0, colorList.length - 1, true);
            // Set the background to the color at that array
            const background = colorList[colorIndex];
            // Remove that color from the options
            colorList.splice(colorIndex, 1);
            // Set the foreground to any other color in the array
            const foreground = random(colorList);
            return {
                foreground,
                background
            };
        }
        async function init() {
            // Get color palettes
            generateNewGrid();
            document.querySelector(".button").addEventListener("click", generateNewGrid);
            const radioButtons = document.querySelectorAll('input[name="toggle"]');
            radioButtons.forEach(radioButton => {
                radioButton.addEventListener('change', () => {
                    encode_as_img_and_link();
                });
            });
        }
        init();

        function encode_as_img_and_link() {
            var svg = document.querySelector(".container svg");
            var container = document.querySelector(".container")
            var colorOne = getComputedStyle(container).getPropertyValue('--color-one');
            var colorTwo = getComputedStyle(container).getPropertyValue('--color-two');
            var colorThree = getComputedStyle(container).getPropertyValue('--color-three');
            var colorFour = getComputedStyle(container).getPropertyValue('--color-four');
            var colorFive = getComputedStyle(container).getPropertyValue('--color-five');
            //get svg source.
            var serializer = new XMLSerializer();
            var source = serializer.serializeToString(svg);
            source = source.replaceAll("var(--color-one)", colorOne)
                .replaceAll("var(--color-two)", colorTwo)
                .replaceAll("var(--color-three)", colorThree)
                .replaceAll("var(--color-four)", colorFour)
                .replaceAll("var(--color-five)", colorFive);
            //convert svg source to URI data scheme.
            var url = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
            url = url.replace("opacity%3D%220%22%", "opacity%3D%22100%22%");
            //set url value to a element's href attribute.
            document.getElementById("test").href = url;
        }
    </script>
</body>

No notes defined.