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