<svg
viewBox="0 0 1000 1000"
width="1000"
height="1000"
role="img"
>
<title>
A geometric pattern composed of nested circles and squiggly lines.
Inspired by Legends of Zelda: Tears of the Kingdom
</title>
<g class="pattern">
<!--
Our graphics code goes here
-->
</g>
</svg>
<button>Randomize</button>
html, body {
display: grid;
place-items: center;
min-height: 100%;
background-color: #eee;
}
svg {
background: #fff;
max-width: 90vw;
max-height: 85vh;
width: auto;
height: auto;
}
.filled-circle {
fill: #fff;
}
.stroked-circle {
fill: none;
stroke: #999;
stroke-width: 10;
}
:root {
--hue: 200;
}
button {
/* Text Colors */
--text-saturation: 90%;
--text-lightness: 40%;
--text-saturation-hover: calc(var(--text-saturation) + 10%);
--text-lightness-hover: calc(var(--text-lightness) - 5%); ;
--text-saturation-active: var(--text-saturation-hover);
--text-lightness-active: calc(var(--text-lightness) - 10%); ;
--text-saturation-disabled: calc(var(--text-saturation) - 60%);
--text-lightness-disabled: calc(var(--text-lightness) + 10%);
/* Background Colors */
--background-saturation: 0%;
--background-lightness: 100%;
--background-saturation-hover: calc(var(--background-saturation) + 80%);
--background-lightness-hover: calc(var(--background-lightness) - 5%);
--background-saturation-active: var(--background-saturation-hover);
--background-lightness-active: calc(var(--background-lightness) - 10%);
--background-saturation-disabled: calc(var(--background-saturation) + 30%);
--background-lightness-disabled: calc(var(--background-lightness) - 10%);
/* Border Colors */
--border-saturation: 90%;
--border-lightness: 60%;
--border-saturation-hover: calc(var(--border-saturation) + 10%);
--border-lightness-hover: calc(var(--border-lightness) - 10%);
--border-saturation-active: var(--border-saturation-hover);
--border-lightness-active: calc(var(--border-lightness) - 20%);
--border-saturation-disabled: calc(var(--border-saturation) - 60%);
--border-lightness-disabled: calc(var(--border-lightness) + 20%);
/* Focus shadow styles */
--shadow-saturation-focus: 100%;
--shadow-lightness-focus: 85%;
/* Color Styles */
color: hsl(var(--hue), var(--text-saturation), var(--text-lightness));
background-color: hsl(var(--hue), var(--background-saturation), var(--background-lightness));
border:0.1em solid hsl(var(--hue), var(--border-saturation), var(--border-lightness));
/* Misc. Styles */
border-radius: 0.25em;
cursor: pointer;
display: inline-block;
font-size: 1em;
padding: 0.5em 1em;
transition-property: box-shadow, background-color, border-color, color;
transition-timing-function: ease-out;
transition-duration: 0.2s;
}
button:hover {
color: hsl(
var(--hue),
var(--text-saturation-hover),
var(--text-lightness-hover)
);
background-color: hsl(
var(--hue),
var(--background-saturation-hover),
var(--background-lightness-hover)
);
border-color: hsl(
var(--hue),
var(--border-saturation-hover),
var(--border-lightness-hover)
);
}
button:active {
color: hsl(
var(--hue),
var(--text-saturation-active),
var(--text-lightness-active)
);
background-color: hsl(
var(--hue),
var(--background-saturation-active),
var(--background-lightness-active)
);
border-color: hsl(
var(--hue),
var(--border-saturation-active),
var(--border-lightness-active)
);
}
button:focus {
outline: none;
box-shadow: 0 0 0 0.25em hsl(
var(--hue),
var(--shadow-saturation-focus),
var(--shadow-lightness-focus)
);
}
import { randomInt } from 'https://unpkg.com/randomness-helpers@0.0.1/dist/index.js';
function circle({ x, y, r, className }) {
return `
<circle
cx="${x}"
cy="${y}"
r="${r}"
class="${className}"
/>
`;
}
function circleGroup({x, y, r }) {
// We'll store all our circles in an array.
const circles = [];
// First, draw a circle with a white background but no border.
// This will hide any elements behind the circle.
circles.push(circle({ x, y, r, className: 'filled-circle' }));
// Decide how much space to put between our circles.
const gap = 20;
// Draw a number of circles, making each one smaller than the last
// until we hit a radius of 0.
let circleSize = r;
while(circleSize > 0) {
circles.push(circle({ x, y, r: circleSize, className: 'stroked-circle' }));
circleSize -= gap;
}
// Return all our circles as a single string;
return circles.join('');
}
const patternEl = document.querySelector('.pattern');
function draw() {
const circleGroups = [];
for (let i = 0; i < randomInt(10, 30); i++) {
circleGroups.push(circleGroup({
x: randomInt(0, 1000),
y: randomInt(0, 1000),
r: randomInt(50, 300)
}))
}
patternEl.innerHTML = circleGroups.join('');
}
draw();
document.querySelector('button').addEventListener('click', draw);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.