Pattern Grid Generator

by vovkasolovev

HTML

<div class="container" id="pattern"></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>

CSS

:root {
  --bg-inner: white;
  --bg-outer: white;
}

* {
  box-sizing: border-box;
}

body {margin:0;
  position: relative;
}

.container {
  height: 100vh;
  width: 100vw;
  background-image: radial-gradient(var(--bg-inner) 0%, var(--bg-outer) 100%);
}
.container svg {
  width: 100%;
  aspect-ratio: 1;
}
.container svg * {
  /*    Removes little gaps between the shapes */
  shape-rendering: geometricprecision;
}

.button {
  position: absolute;
  bottom: 0;
  right: 0;
  padding: 0.5rem;
  margin: 0;
  border-top-left-radius: 12px;
  background: #ffffffcc;
  border: 0.5px solid #555555cc;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  font-weight: 600;
  color: #333;
  font-size: 0.75rem;
}
.button svg {
  width: 1.25rem;
}
.button:hover svg {
  transform: rotate(-45deg);
}
.button:focus, .button:active {
  outline: 2px solid #f06;
}
.button:focus svg, .button:active svg {
  transform: rotate(-90deg);
}

JavaScript

/* https://frontend.horse/articles/generative-grids/ */

import { SVG } from "https://cdn.skypack.dev/@svgdotjs/[email protected]";
import { random } from "https://cdn.skypack.dev/@georgedoescode/[email protected]";
import tinycolor from "https://cdn.skypack.dev/[email protected]";


console.clear();

let draw, squareSize, numRows, numCols, colors, colorPalette;
const selectedCharacters = [
  "A",
  "B",
  "C",
  "D",
  "E",
  "F",
  "G",
  "H",
  "I",
  "J",
  "K",
  "L",
  "M",
  "N",
  // O removed for looking like a circle
  "P",
  // Q removed for an annoying descender
  "R",
  "S",
  "T",
  "U",
  "V",
  "W",
  "X",
  "Y",
  "Z",
  "&"
];

/*
Block Design Functions
*/

function drawCircle(x, y, foreground, background) {
  // Create group element
  const group = draw.group().addClass("draw-circle");

  // Draw Background
  group.rect(squareSize+2, squareSize+5).fill(background).move(x-1, y-1);

  // 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 = (squareSize/size) -(offset);
  const space = (squareSize - (offset) - (circleSize * (size-1)));

  // Draw Background
  group.rect(squareSize+2, squareSize+2).fill(background).move(x-1, y-1);

  // 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
 ...