Skip to content

Instantly share code, notes, and snippets.

@LeetCodes
Created November 28, 2021 07:57
Show Gist options
  • Save LeetCodes/1df8d61f43997c45c8aa446c06c0fe6d to your computer and use it in GitHub Desktop.
Save LeetCodes/1df8d61f43997c45c8aa446c06c0fe6d to your computer and use it in GitHub Desktop.
NWaKvKx
<canvas id="canvas"></canvas>
<div id="hud">
<div id="msg"></div>
<div id="algos"></div>
</div>
<div id="help">
<div>
<h1>THE SPIRAL</h1>
<h4>Music Player / Visualizer v1.0.0</h4>
<h3>HELP SCREEN</h3>
</div>
<div class="text">
<p>Not indicated for people susceptible to rapid flashing lights.</p>
<p>Best in <span class="keys">full-screen (press F key)</span> and accompanied by your favorite music playlist. If key commands aren't working click on screen first to focus it.</p>
<p>PLAYER: <span class="keys"> Click Add Track(s) to select one or multiple audio files</span> from your device (as long as the device supports it). The files get added to the playlist (scroll to see as only one gets shown to save space). Use the controls to play, stop etc. and click on the progress bar to skip.<span class="keys"> Use the P key to hide / show the player.</span> When a track is finished the next one will play and the playlist will loop.</p>
<p>VISUALIZER: Spiral will do it's own thing or you can <span class="keys">click, touch or press space bar to create a new spiral</span>.
Changes algorithm every 100 seconds by default, <span class="keys">press I key to increase </span> by 10 seconds or <span class="keys">D to decrease.</span> Or press <span class="keys">M to toggle between auto-changing and manual mode. </span> These will take effect after the next change.</p>
<p>The algorithm name is displayed on screen when it changes. <span class="keys">Press S for silence mode to toggle it on/off. </span>
<p><span class="help">H to open / close the help screen.</span></p>
</div>
</div>
<div id="player">
<div id="picker">
<label id="click-label" for="input">Add Track(s)</label>
<input type="file" id="input" accept="audio/*" multiple>
<ol id="playlist">
</ol>
<div id="controls">
<button id="prev">
<ion-icon name="play-skip-back-outline"></ion-icon>
</button>
<button id="play">
<ion-icon id="play-pause-icon" name="play-outline"></ion-icon>
</button>
<button id="stop">
<ion-icon name="stop-outline"></ion-icon>
</button>
<button id="next">
<ion-icon name="play-skip-forward-outline"></ion-icon>
</button>
</div>
</div>
<div id="progress">
<progress id="progress-percent" max="100" value="0"></progress>
</div>
</div>
<audio id="audio"></audio>
CanvasRenderingContext2D.prototype.roundRect = function (
x,
y,
width,
height,
radius,
fill,
stroke
) {
const cornerRadius = {
upperLeft: 0,
upperRight: 0,
lowerLeft: 0,
lowerRight: 0
};
if (typeof stroke == "undefined") {
stroke = true;
}
if (typeof radius === "object") {
for (let side in radius) {
cornerRadius[side] = radius[side];
}
}
this.beginPath();
this.moveTo(x + cornerRadius.upperLeft, y);
this.lineTo(x + width - cornerRadius.upperRight, y);
this.quadraticCurveTo(x + width, y, x + width, y + cornerRadius.upperRight);
this.lineTo(x + width, y + height - cornerRadius.lowerRight);
this.quadraticCurveTo(
x + width,
y + height,
x + width - cornerRadius.lowerRight,
y + height
);
this.lineTo(x + cornerRadius.lowerLeft, y + height);
this.quadraticCurveTo(x, y + height, x, y + height - cornerRadius.lowerLeft);
this.lineTo(x, y + cornerRadius.upperLeft);
this.quadraticCurveTo(x, y, x + cornerRadius.upperLeft, y);
this.closePath();
if (stroke) {
this.stroke();
}
if (fill) {
this.fill();
}
};
// DOM References
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
const hud = document.querySelector("#hud");
const msg = document.querySelector("#msg");
const algosDisplay = document.querySelector("#algos");
const help = document.querySelector("#help");
// VARIABLES
// canvas to window size
let w = (canvas.width = window.innerWidth);
let h = (canvas.height = window.innerHeight);
// time-frame
let t = 0;
// for the animations
let stagger = 1;
let speed = 5;
// for repeats
let interval;
let regen;
let autoChange = 30;
let manual = false;
// hud messages
let silent = false;
let helpView = false;
let algoTimer;
let msgTimer;
// algorithms list
const ALGOS = [
"epic-rays",
"abstractions",
"medusa",
"chillout",
"swirls",
"mirage",
"majestic",
"wormhole",
"irradiate",
"entropy",
"tripping",
"progression",
"aperture",
"upholstery",
"unfocused",
"rotunda",
"crayon-funnel",
"big-bangs",
"nazca",
"clutch",
"torus",
"shapeshifter",
"smooth",
"encoded",
"concentric",
"glow",
"blends",
"matter",
"seeds",
"onion",
"spheral",
"snakes-ladders",
"cornucopia",
"cornucopia2",
"crosshatch",
"networks",
"spikral",
"fruits",
"zentangles",
"typobrush",
"veils",
"harmonie",
"portals",
"sandala",
"ghostly-shapes",
"psycho-rainbow",
"hallucinate",
"hive",
"boxes",
"digital-art"
];
// stores the last played algorithms
let LAST_ALGOS = [];
// choose a new algorithm that is not on the last x played
function chooseAlgos() {
let picks = ALGOS.filter((algo) => !LAST_ALGOS.includes(algo));
let choose = picks[random(0, picks.length)];
LAST_ALGOS.push(choose);
if (LAST_ALGOS.length > 20) LAST_ALGOS.shift();
// setup the chosen algorithm
switch (choose) {
case "epic-rays":
displayAlgos("EPIC RAYS");
ctx.save();
runningAlgo = new EpicRays();
runningAlgo.draw();
break;
case "abstractions":
displayAlgos("ABSTRACTIONS");
ctx.save();
runningAlgo = new Abstractions();
runningAlgo.draw();
break;
case "medusa":
displayAlgos("MEDUSA");
ctx.save();
runningAlgo = new Medusa();
runningAlgo.draw();
break;
case "chillout":
displayAlgos("CHILL OUT");
ctx.save();
runningAlgo = new Chillout();
runningAlgo.draw();
break;
case "swirls":
displayAlgos("SWIRLS");
ctx.save();
runningAlgo = new Swirls();
runningAlgo.draw();
break;
case "mirage":
displayAlgos("MIRAGE");
ctx.save();
runningAlgo = new Mirage();
runningAlgo.draw();
break;
case "majestic":
displayAlgos("MAJESTIC");
ctx.save();
runningAlgo = new Majestic();
runningAlgo.draw();
break;
case "wormhole":
displayAlgos("WORMHOLE");
ctx.save();
runningAlgo = new Wormhole();
runningAlgo.draw();
break;
case "irradiate":
displayAlgos("IRRADIATE");
ctx.save();
runningAlgo = new Irradiate();
runningAlgo.draw();
break;
case "entropy":
displayAlgos("ENTROPY");
ctx.save();
runningAlgo = new Entropy();
runningAlgo.draw();
break;
case "tripping":
displayAlgos("TRIPPING");
ctx.save();
runningAlgo = new Tripping();
runningAlgo.draw();
break;
case "progression":
displayAlgos("PROGRESSION");
ctx.save();
runningAlgo = new Progression();
runningAlgo.draw();
break;
case "aperture":
displayAlgos("APERTURE");
ctx.save();
runningAlgo = new Aperture();
runningAlgo.draw();
break;
case "upholstery":
displayAlgos("UPHOLSTERY");
ctx.save();
runningAlgo = new Upholstery();
runningAlgo.draw();
break;
case "unfocused":
displayAlgos("UNFOCUSED");
ctx.save();
runningAlgo = new Unfocused();
runningAlgo.draw();
break;
case "rotunda":
displayAlgos("ROTUNDA");
ctx.save();
runningAlgo = new Rotunda();
runningAlgo.draw();
break;
case "crayon-funnel":
displayAlgos("CRAYON FUNNEL");
ctx.save();
runningAlgo = new CrayonFunnel();
runningAlgo.draw();
break;
case "big-bangs":
displayAlgos("BIG BANGS");
ctx.save();
runningAlgo = new BigBangs();
runningAlgo.draw();
break;
case "nazca":
displayAlgos("NAZCA");
ctx.save();
runningAlgo = new Nazca();
runningAlgo.draw();
break;
case "clutch":
displayAlgos("CLUTCH");
ctx.save();
runningAlgo = new Clutch();
runningAlgo.draw();
break;
case "torus":
displayAlgos("TORUS");
ctx.save();
runningAlgo = new Torus();
runningAlgo.draw();
break;
case "shapeshifter":
displayAlgos("SHAPESHIFTER");
ctx.save();
runningAlgo = new Shapeshifter();
runningAlgo.draw();
break;
case "smooth":
displayAlgos("SMOOTH");
ctx.save();
runningAlgo = new Smooth();
runningAlgo.draw();
break;
case "encoded":
displayAlgos("ENCODED");
ctx.save();
runningAlgo = new Encoded();
runningAlgo.draw();
break;
case "concentric":
displayAlgos("CONCENTRIC");
ctx.save();
runningAlgo = new Concentric();
runningAlgo.draw();
break;
case "glow":
displayAlgos("GLOW");
ctx.save();
runningAlgo = new Glow();
runningAlgo.draw();
break;
case "blends":
displayAlgos("BLENDS");
ctx.save();
runningAlgo = new Blends();
runningAlgo.draw();
break;
case "matter":
displayAlgos("MATTER");
ctx.save();
runningAlgo = new Matter();
runningAlgo.draw();
break;
case "seeds":
displayAlgos("SEEDS");
ctx.save();
runningAlgo = new Seeds();
runningAlgo.draw();
break;
case "onion":
displayAlgos("ONION");
ctx.save();
runningAlgo = new Onion();
runningAlgo.draw();
break;
case "spheral":
displayAlgos("SPHERAL");
ctx.save();
runningAlgo = new Spheral();
runningAlgo.draw();
break;
case "snakes-ladders":
displayAlgos("SNAKES 'N LADDERS");
ctx.save();
runningAlgo = new SnakesLadders();
runningAlgo.draw();
break;
case "cornucopia":
displayAlgos("CORNUCOPIA");
ctx.save();
runningAlgo = new Cornucopia();
runningAlgo.draw();
break;
case "cornucopia2":
displayAlgos("CORNUCOPIA 2");
ctx.save();
runningAlgo = new Cornucopia2();
runningAlgo.draw();
break;
case "crosshatch":
displayAlgos("CROSSHATCH");
ctx.save();
runningAlgo = new Crosshatch();
runningAlgo.draw();
break;
case "networks":
displayAlgos("NETWORKS");
ctx.save();
runningAlgo = new Networks();
runningAlgo.draw();
break;
case "spikral":
displayAlgos("SPIKRAL");
ctx.save();
runningAlgo = new Spikral();
runningAlgo.draw();
break;
case "fruits":
displayAlgos("FRUITS");
ctx.save();
runningAlgo = new Fruits();
runningAlgo.draw();
break;
case "zentangles":
displayAlgos("ZENTANGLES");
ctx.save();
runningAlgo = new Zentangles();
runningAlgo.draw();
break;
case "typobrush":
displayAlgos("TYPO BRUSH");
ctx.save();
runningAlgo = new Typobrush();
runningAlgo.draw();
break;
case "veils":
displayAlgos("VEILS");
ctx.save();
runningAlgo = new Veils();
runningAlgo.draw();
break;
case "harmonie":
displayAlgos("HARMONIE");
ctx.save();
runningAlgo = new Harmonie();
runningAlgo.draw();
break;
case "portals":
displayAlgos("PORTALS");
ctx.save();
runningAlgo = new Portals();
runningAlgo.draw();
break;
case "sandala":
displayAlgos("SANDALA");
ctx.save();
runningAlgo = new Sandala();
runningAlgo.draw();
break;
case "ghostly-shapes":
displayAlgos("GHOSTLY SHAPES");
ctx.save();
runningAlgo = new GhostlyShapes();
runningAlgo.draw();
break;
case "psycho-rainbow":
displayAlgos("PSYCHO RAINBOW");
ctx.save();
runningAlgo = new PsychoRainbow();
runningAlgo.draw();
break;
case "hallucinate":
displayAlgos("HALLUCINATE");
ctx.save();
runningAlgo = new Hallucinate();
runningAlgo.draw();
break;
case "hive":
displayAlgos("THE HIVE");
ctx.save();
runningAlgo = new Hive();
runningAlgo.draw();
break;
case "boxes":
displayAlgos("BOXES");
ctx.save();
runningAlgo = new Boxes();
runningAlgo.draw();
break;
case "digital-art":
displayAlgos("DIGITAL ART");
ctx.save();
runningAlgo = new DigitalArt();
runningAlgo.draw();
break;
}
}
// ALGORITHMS / SPIRALS CLASSES
class EpicRays {
constructor() {
this.pointAx = random(0, w);
this.pointAy = random(0, h);
this.pointBx = random(0, w);
this.pointBy = random(0, h);
this.pointCx = random(0, w);
this.pointCy = random(0, h);
this.rotations = [
1,
2,
3,
4,
7,
8,
11,
13,
14,
16,
17,
19,
21,
22,
23,
26,
28,
29,
31,
32,
33,
34,
37,
38,
39,
41,
43
];
this.rotate = this.rotations[random(0, this.rotations.length)];
ctx.strokeStyle = randomColor(40, 255, 0.25, 0.5);
speed = 3;
this.draw = () => {
if (t % speed === 0) {
stagger = stagger % 4;
if (stagger === 0) {
ctx.beginPath();
ctx.moveTo(w / 2, h / 2);
ctx.lineTo(this.pointAx, this.pointAy);
ctx.stroke();
}
if (stagger === 1) {
ctx.beginPath();
ctx.moveTo(this.pointAx, this.pointAy);
ctx.lineTo(this.pointBx, this.pointBy);
ctx.stroke();
}
if (stagger === 2) {
ctx.beginPath();
ctx.moveTo(this.pointBx, this.pointBy);
ctx.lineTo(this.pointCx, this.pointCy);
ctx.stroke();
}
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
stagger++;
t++;
if (t % (speed * 300) === 0) {
ctx.strokeStyle = randomColor(40, 255, 0.25, 0.5);
this.pointAx = random(0, w);
this.pointAy = random(0, h);
this.pointBx = random(0, w);
this.pointBy = random(0, h);
this.pointCx = random(0, w);
this.pointCy = random(0, h);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Abstractions {
constructor() {
this.pointAx = random(0, w);
this.pointAy = random(0, h);
this.pointCpAx = random(0, w);
this.pointCpAy = random(0, h);
this.pointBx = random(0, w);
this.pointBy = random(0, h);
this.pointCpBx = random(0, w);
this.pointCpBy = random(0, h);
this.pointCx = random(0, w);
this.pointCy = random(0, h);
this.pointCpCx = random(0, w);
this.pointCpCy = random(0, h);
this.rotations = [
1,
2,
3,
4,
7,
8,
11,
13,
14,
16,
17,
19,
21,
22,
23,
26,
28,
29,
31,
32,
33,
34,
37,
38,
39,
41,
43
];
this.rotate = this.rotations[random(0, this.rotations.length)];
speed = 3;
ctx.shadowColor = ctx.strokeStyle = randomColor(0, 255, 0.25, 0.45);
ctx.shadowBlur = 3;
this.draw = () => {
if (t % speed === 0) {
stagger = stagger % 4;
if (stagger === 0) {
ctx.beginPath();
ctx.moveTo(this.pointCx, this.pointCy);
ctx.quadraticCurveTo(
this.pointCpAx,
this.pointCpAy,
this.pointAx,
this.pointAy
);
ctx.stroke();
}
if (stagger === 1) {
ctx.beginPath();
ctx.moveTo(this.pointAx, this.pointAy);
ctx.quadraticCurveTo(
this.pointCpBx,
this.pointCpBy,
this.pointBx,
this.pointBy
);
ctx.stroke();
}
if (stagger === 2) {
ctx.beginPath();
ctx.moveTo(this.pointBx, this.pointBy);
ctx.quadraticCurveTo(
this.pointCpCx,
this.pointCpCy,
this.pointCx,
this.pointCy
);
ctx.stroke();
}
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
stagger++;
t++;
if (t % (speed * 180) === 0) {
ctx.shadowColor = ctx.strokeStyle = randomColor(0, 255, 0.25, 0.45);
this.pointAx = random(0, w);
this.pointAy = random(0, h);
this.pointCpAx = random(0, w);
this.pointCpAy = random(0, h);
this.pointBx = random(0, w);
this.pointBy = random(0, h);
this.pointCpBx = random(0, w);
this.pointCpBy = random(0, h);
this.pointCx = random(0, w);
this.pointCy = random(0, h);
this.pointCpCx = random(0, w);
this.pointCpCy = random(0, h);
this.rotate = this.rotations[random(0, this.rotations.length)];
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Medusa {
constructor() {
this.pointAx = random(0, w);
this.pointAy = random(0, h);
this.pointCpAx = random(0, w);
this.pointCpAy = random(0, h);
this.pointBx = random(0, w);
this.pointBy = random(0, h);
this.pointCpBx = random(0, w);
this.pointCpBy = random(0, h);
this.pointCx = random(0, w);
this.pointCy = random(0, h);
this.pointCpCx = random(0, w);
this.pointCpCy = random(0, h);
this.rotate = random(1, 19);
ctx.strokeStyle = randomColor(0, 185, 0.3, 0.65);
speed = 3;
ctx.globalCompositeOperation = "overlay";
this.draw = () => {
if (t % speed === 0) {
stagger = stagger % 4;
if (stagger === 0) {
ctx.beginPath();
ctx.moveTo(this.pointCpCx, this.pointCpCy);
ctx.quadraticCurveTo(
this.pointCpAx,
this.pointCpAy,
this.pointAx++,
this.pointAy--
);
ctx.stroke();
}
if (stagger === 1) {
ctx.beginPath();
ctx.moveTo(this.pointCpAx, this.pointCpAy);
ctx.quadraticCurveTo(
this.pointCpBx,
this.pointCpBy++,
this.pointBx,
this.pointBy
);
ctx.stroke();
}
if (stagger === 2) {
ctx.beginPath();
ctx.moveTo(this.pointCpBx, this.pointCpBy);
ctx.quadraticCurveTo(
this.pointCpCx--,
this.pointCpCy,
this.pointCx,
this.pointCy
);
ctx.stroke();
}
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate++ * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
stagger++;
t++;
if (t % (speed * 450) === 0) {
ctx.clearRect(-w, -h, 3 * w, 3 * h);
ctx.strokeStyle = randomColor(0, 185, 0.3, 0.65);
this.pointAx = random(0, w);
this.pointAy = random(0, h);
this.pointCpAx = random(0, w);
this.pointCpAy = random(0, h);
this.pointBx = random(0, w);
this.pointBy = random(0, h);
this.pointCpBx = random(0, w);
this.pointCpBy = random(0, h);
this.pointCx = random(0, w);
this.pointCy = random(0, h);
this.pointCpCx = random(0, w);
this.pointCpCy = random(0, h);
this.rotate = random(1, 19);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Chillout {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.rotate = random(1, 10);
ctx.lineWidth = random(1, 5);
ctx.strokeStyle = randomColor(0, 255, 0.4, 1);
ctx.filter = "saturate(17.5%)";
this.draw = () => {
if (t % speed === 0) {
ctx.moveTo(this.x3, this.y3);
ctx.quadraticCurveTo(this.x2, this.y2, this.x1, this.y1);
ctx.stroke();
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
}
t++;
if (t % (speed * 80) === 0) {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
ctx.beginPath();
ctx.lineWidth = random(1, 5);
ctx.strokeStyle = randomColor(0, 255, 0.4, 1);
this.rotate = random(1, 10);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Swirls {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.rotate = random(1, 10);
ctx.strokeStyle = randomColor(0, 255, 0.4, 0.7);
ctx.lineWidth = 0.1;
this.draw = () => {
if (t % speed === 0) {
ctx.moveTo(this.x3, this.y3);
ctx.quadraticCurveTo(this.x2, this.y2, this.x1, this.y1);
ctx.stroke();
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
}
t++;
if (t % (speed * 240) === 0) {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
ctx.beginPath();
ctx.strokeStyle = randomColor(0, 255, 0.4, 0.7);
this.rotate = random(1, 10);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Mirage {
constructor() {
this.width = random(100, w);
this.height = random(100, h);
this.ul = random(10, 300);
this.ur = random(10, 300);
this.ll = random(10, 300);
this.lr = random(10, 300);
this.rotate = random(1, 50);
ctx.fillStyle = randomColor(0, 255, 0.01, 0.05);
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
w / 2 - this.width / 2,
h / 2 - this.height / 2,
this.width,
this.height,
{
upperLeft: this.ul,
upperRight: this.ur,
lowerLeft: this.ll,
lowerRight: this.lr
},
true,
false
);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 200) === 0) {
ctx.fillRect(-w, -h, 3 * w, 3 * h);
this.width = random(100, w);
this.height = random(100, h);
this.ul = random(10, 300);
this.ur = random(10, 300);
this.ll = random(10, 300);
this.lr = random(10, 300);
this.rotate = random(1, 50);
ctx.fillStyle = randomColor(0, 255, 0.01, 0.05);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Majestic {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.width = random(30, w);
this.height = random(30, h);
this.ul = random(10, w);
this.ur = random(10, h);
this.ll = random(10, h);
this.lr = random(10, w);
this.rotate = random(1, 359);
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.01, 0.05);
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
this.x,
this.y,
this.width,
this.height,
{
upperLeft: this.ul,
upperRight: this.ur,
lowerLeft: this.ll,
lowerRight: this.lr
},
true,
true
);
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 180) === 0) {
ctx.fillRect(-w, -h, 3 * w, 3 * h);
this.width = random(30, w);
this.height = random(30, h);
this.x = random(0, w);
this.y = random(0, h);
this.ul = random(10, w);
this.ur = random(10, h);
this.ll = random(10, h);
this.lr = random(10, w);
this.rotate = random(1, 359);
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.01, 0.05);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Wormhole {
constructor() {
this.x = random(50, w - 50);
this.y = random(50, h - 50);
this.width = random(30, w);
this.height = random(30, h);
this.ul = random(10, 50);
this.ur = random(10, 50);
this.ll = random(10, 50);
this.lr = random(10, 50);
this.rotate = random(1, 44);
ctx.strokeStyle = randomColor(0, 255, 0.2, 0.5);
ctx.fillStyle = randomColor(0, 255, 0.01, 0.01);
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
this.x,
this.y,
this.width,
this.height,
{
upperLeft: this.ul,
upperRight: this.ur,
lowerLeft: this.ll,
lowerRight: this.lr
},
true,
true
);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
this.width++;
this.height++;
this.ul++;
this.ur++;
t++;
if (t % (speed * 360) === 0) {
this.width = random(30, w);
this.height = random(30, h);
this.x = random(50, w - 50);
this.y = random(50, h - 50);
this.ul = random(10, 50);
this.ur = random(10, 50);
this.ll = random(10, 50);
this.lr = random(10, 50);
this.rotate = random(1, 44);
ctx.strokeStyle = randomColor(0, 255, 0.2, 0.5);
ctx.fillStyle = randomColor(0, 255, 0.01, 0.01);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Irradiate {
constructor() {
this.width = random(50, w / 2);
this.height = random(50, h / 2);
this.rotate = random(1, 181);
this.ul = random(10, Math.min(w, h));
this.ur = random(10, Math.min(w, h));
this.ll = random(10, Math.min(w, h));
this.lr = random(10, Math.min(w, h));
ctx.strokeStyle = randomColor(0, 255, 0.33);
ctx.globalCompositeOperation = "hard-light";
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
w / 2 - this.width / 2,
h / 2 - this.height / 2,
this.width,
this.height,
{
upperLeft: this.ul,
upperRight: this.ur,
lowerLeft: this.ll,
lowerRight: this.lr
}
);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 150) === 0) {
ctx.beginPath();
this.width = random(50, w / 2);
this.height = random(50, h / 2);
this.rotate = random(1, 181);
this.ul = random(10, Math.min(w, h));
this.ur = random(10, Math.min(w, h));
this.ll = random(10, Math.min(w, h));
this.lr = random(10, Math.min(w, h));
ctx.strokeStyle = randomColor(0, 255, 0.33);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Entropy {
constructor() {
this.width = random(50, w);
this.height = random(50, h);
this.rotate = random(1, 181);
this.ul = random(10, Math.min(w, h));
this.ur = random(10, Math.min(w, h));
this.ll = random(10, Math.min(w, h));
this.lr = random(10, Math.min(w, h));
ctx.strokeStyle = randomColor(0, 255, 0.75);
ctx.globalCompositeOperation = "overlay";
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(0, 0, this.width++, this.height++, {
upperLeft: this.ul--,
upperRight: this.ur--,
lowerLeft: this.ll--,
lowerRight: this.lr--
});
ctx.roundRect(w, h, this.height, this.width, {
upperLeft: this.lr,
upperRight: this.ll,
lowerLeft: this.ur,
lowerRight: this.ul
});
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 500) === 0) {
ctx.beginPath();
this.width = random(50, w);
this.height = random(50, h);
this.rotate = random(1, 181);
this.ul = random(10, Math.min(w, h));
this.ur = random(10, Math.min(w, h));
this.ll = random(10, Math.min(w, h));
this.lr = random(10, Math.min(w, h));
ctx.strokeStyle = randomColor(0, 255, 0.75);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Tripping {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.width = random(50, w);
this.height = random(50, h);
this.rotate = random(1, 360);
this.ul = random(10, Math.max(w, h));
this.ur = random(10, Math.max(w, h));
this.ll = random(10, Math.max(w, h));
this.lr = random(10, Math.max(w, h));
ctx.strokeStyle = randomColor(0, 255, 0.25, 0.5);
ctx.lineWidth = 0.5;
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(this.x1++, this.y1++, this.width++, this.height++, {
upperLeft: this.ul--,
upperRight: this.ur--,
lowerLeft: this.ll--,
lowerRight: this.lr--
});
ctx.roundRect(this.x2--, this.y2--, this.height, this.width, {
upperLeft: this.lr,
upperRight: this.ll,
lowerLeft: this.ur,
lowerRight: this.ul
});
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 500) === 0) {
ctx.beginPath();
ctx.clearRect(-w, -h, 3 * w, 3 * h);
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.width = random(50, w);
this.height = random(50, h);
this.rotate = random(1, 360);
this.ul = random(10, Math.max(w, h));
this.ur = random(10, Math.max(w, h));
this.ll = random(10, Math.max(w, h));
this.lr = random(10, Math.max(w, h));
ctx.strokeStyle = randomColor(0, 255, 0.25, 0.5);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Progression {
constructor() {
this.width = random(40, w);
this.height = random(40, h);
this.round = random(1, 350);
this.rotate = random(1, 180);
ctx.fillStyle = randomColor(0, 255, 0.01, 0.03);
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
w / 2,
h / 2,
this.width,
this.height,
{
upperLeft: this.round,
upperRight: this.round,
lowerLeft: this.round,
lowerRight: this.round
},
true,
false
);
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 180) === 0) {
this.width = random(40, w);
this.height = random(40, h);
this.round = random(1, 350);
this.rotate = random(1, 180);
ctx.beginPath();
ctx.fillStyle = randomColor(0, 255, 0.01, 0.03);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Aperture {
constructor() {
this.x = w / 2;
this.y = random(100, h - 100);
this.width = random(100, w - 100);
this.height = random(100, h - 100);
this.round = random(5, 100);
this.white = true;
this.rotate = random(1, 70);
this.incX = Math.random();
this.incH = Math.random();
ctx.strokeStyle = "white";
ctx.fillStyle = "black";
ctx.globalAlpha = 0.75;
ctx.lineWidth = 4;
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
this.x,
this.y,
this.width,
this.height,
{
upperLeft: this.round,
upperRight: this.round,
lowerLeft: this.round,
lowerRight: this.round
},
true
);
}
this.x += this.incX;
this.height += this.incH;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 300) === 0) {
ctx.beginPath();
if (this.white) {
ctx.strokeStyle = "black";
ctx.fillStyle = "white";
} else {
ctx.strokeStyle = "white";
ctx.fillStyle = "black";
}
this.white = !this.white;
this.x = w / 2;
this.y = random(100, h - 100);
this.rotate = random(1, 70);
this.width = random(100, w - 100);
this.height = random(100, h - 100);
this.round = random(5, 100);
this.incX = Math.random();
this.incH = Math.random();
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Upholstery {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.rotate = random(1, 55);
this.dash1 = random(1, 15);
this.dash2 = random(20, 40);
this.dash3 = random(1, 50);
ctx.strokeStyle = randomColor(50, 255, 1, 1);
ctx.setLineDash([this.dash1, this.dash2, this.dash3]);
ctx.globalCompositeOperation = "overlay";
this.draw = () => {
if (t % speed === 0) {
ctx.moveTo(this.x1, this.y1);
ctx.lineTo(this.x2, this.y2);
ctx.stroke();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 120) === 0) {
this.dash1 = random(1, 15);
this.dash2 = random(20, 40);
this.dash3 = random(1, 50);
ctx.setLineDash([this.dash1, this.dash2, this.dash3]);
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
ctx.beginPath();
ctx.strokeStyle = randomColor(50, 255, 1, 1);
this.rotate = random(1, 55);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Unfocused {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.radius1 = random(5, 55);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.radius2 = random(5, 55);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.radius3 = random(5, 55);
this.rotate = random(1, 61);
ctx.fillStyle = randomColor(10, 255, 0.1, 0.1);
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x1, this.y1, this.radius1, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(this.x2, this.y2, this.radius2, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(this.x3, this.y3, this.radius3, 0, 2 * Math.PI);
ctx.fill();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 20) === 0) {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.radius1 = random(5, 55);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.radius2 = random(5, 55);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.radius3 = random(5, 55);
ctx.fillStyle = randomColor(10, 255, 0.1, 0.1);
}
if (t % (speed * 100) === 0) {
this.rotate = random(1, 61);
}
if (t % (speed * 500) === 0) {
ctx.fillStyle = "rgba(0,0,0,0.5)";
ctx.fillRect(-w, -h, 3 * w, 3 * h);
ctx.fillStyle = randomColor(10, 255, 0.1, 0.1);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Rotunda {
constructor() {
this.x1 = random(0, w / 3);
this.y1 = random(0, h / 3);
this.radius1 = random(5, 150);
this.x2 = random(w / 3, w * 0.66);
this.y2 = random(w / 3, h * 0.66);
this.radius2 = random(5, 150);
this.x3 = random(w * 0.66, w);
this.y3 = random(h * 0.66, h);
this.radius3 = random(5, 150);
this.rotate = random(3, 31);
ctx.strokeStyle = randomColor(10, 255, 0.25, 0.5);
ctx.globalCompositeOperation = "overlay";
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x1, this.y1, this.radius1, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(this.x2, this.y2, this.radius2, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(this.x3, this.y3, this.radius3, 0, 2 * Math.PI);
ctx.stroke();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 150) === 0) {
this.x1 = random(0, w / 3);
this.y1 = random(0, h / 3);
this.radius1 = random(5, 150);
this.x2 = random(w / 3, w * 0.66);
this.y2 = random(w / 3, h * 0.66);
this.radius2 = random(5, 150);
this.x3 = random(w * 0.66, w);
this.y3 = random(h * 0.66, h);
this.radius3 = random(5, 150);
this.rotate = random(3, 31);
ctx.strokeStyle = randomColor(10, 255, 0.25, 0.5);
this.rotate = random(3, 31);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class CrayonFunnel {
constructor() {
this.x = random(w / 3, w * 0.66);
this.y = random(w / 3, h * 0.66);
this.inc = random(1, 6);
this.radius = random(5, 60);
this.rotate = random(1, 150);
ctx.strokeStyle = randomColor(0, 255, 1, 1);
ctx.lineWidth = 2;
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
this.radius += this.inc;
ctx.stroke();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 180) === 0) {
this.x = random(w / 3, w * 0.66);
this.y = random(w / 3, h * 0.66);
this.radius = random(5, 60);
this.inc = random(1, 6);
this.rotate = random(1, 150);
if (Math.random() < 0.5) {
if (Math.random() < 0.5) {
ctx.strokeStyle = "white";
} else {
ctx.strokeStyle = "black";
}
} else {
ctx.strokeStyle = randomColor(0, 255, 1, 1);
}
}
interval = requestAnimationFrame(this.draw);
};
}
}
class BigBangs {
constructor() {
this.r = 1;
this.i = random(5, 30);
this.a = random(1, 180);
ctx.fillStyle = randomColor(0, 255, 0.02, 0.05);
ctx.strokeStyle = randomColor(0, 255, 0.5, 1);
ctx.globalCompositeOperation = "hard-light";
this.draw = () => {
if (t % speed === 0) {
ctx.arc(w / 2, h / 2, this.r, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
this.r += this.i;
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.a * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
t++;
if (this.r > Math.max(w, h)) {
ctx.fillStyle = randomColor(0, 255, 0.02, 0.05);
ctx.fillRect(-w, -h, 3 * w, 3 * h);
this.a = random(1, 180);
this.r = 1;
this.i = random(5, 30);
ctx.beginPath();
ctx.strokeStyle = randomColor(0, 255, 0.5, 1);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Nazca {
constructor() {
this.r = 1;
this.i = random(13, 60);
this.a = random(1, 180);
this.modes = ["soft-light", "overlay", "color"];
this.cycles = 0;
ctx.fillStyle = randomColor(0, 255, 0.15, 0.55);
ctx.strokeStyle = randomColor(0, 255, 0.75, 1);
ctx.globalCompositeOperation = "soft-light";
this.draw = () => {
if (t % speed === 0) {
ctx.arc(w / 2, h / 2, this.r, 0, Math.random() * Math.PI);
ctx.fill();
ctx.stroke();
this.r += this.i;
}
ctx.translate(w / 2, h / 2);
ctx.rotate(-this.a);
ctx.translate(-w / 2, -h / 2);
t++;
if (this.r > Math.max(w, h)) {
this.cycles++;
if (this.cycles % 10 === 0) {
ctx.globalCompositeOperation = this.modes[
random(0, this.modes.length)
];
}
ctx.lineWidth = random(1, 7);
ctx.fillStyle = randomColor(0, 255, 0.15, 0.55);
this.a = random(1, 180);
this.r = 1;
this.i = random(13, 60);
ctx.beginPath();
ctx.strokeStyle = randomColor(0, 255, 0.75, 1);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Clutch {
constructor() {
this.x1 = random(100, w - 100);
this.y1 = random(100, h - 100);
this.r1 = random(75, 360);
this.rotate = random(1, 10);
this.true = true;
ctx.shadowColor = ctx.strokeStyle = randomColor(0, 255, 0.65);
ctx.shadowBlur = 3;
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(
this.x1,
this.y1,
this.r1,
Math.PI / (this.true ? 2 : 3),
Math.PI / (this.true ? 3 : 2),
this.true
);
ctx.stroke();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 225) === 0) {
this.x1 = random(100, w - 100);
this.y1 = random(100, h - 100);
this.r1 = random(75, 600);
this.true = !this.true;
this.rotate = random(1, 10);
ctx.shadowColor = ctx.strokeStyle = randomColor(0, 255, 0.65);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Torus {
constructor() {
this.r1 = random(120, 500);
this.x1 = random(this.r1 / 2, w - this.r1 / 2);
this.y1 = random(this.r1 / 2, h - this.r1 / 2);
this.color1 = randomColor(0, 255, 0.06, 0.16);
this.rotate = random(6, 24);
ctx.strokeStyle = "black";
this.draw = () => {
if (t % speed === 0) {
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate * Math.PI) / 180);
ctx.beginPath();
ctx.fillStyle = this.color1;
ctx.arc(this.x1, this.y1, this.r1, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.translate(-w / 2, -h / 2);
}
t++;
if (t % (speed * 60) === 0) {
this.r1 = random(120, 500);
this.x1 = random(this.r1 / 2, w - this.r1 / 2);
this.y1 = random(this.r1 / 2, h - this.r1 / 2);
this.color1 = randomColor(0, 255, 0.06, 0.16);
this.rotate = random(6, 24);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Shapeshifter {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.x4 = random(0, w);
this.y4 = random(0, h);
this.rotate = (random(4, 87) * Math.PI) / 180;
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.01, 0.01);
ctx.shadowColor = "black";
ctx.shadowBlur = 20;
ctx.moveTo(this.x1, this.y1);
this.draw = () => {
if (t % speed === 0) {
stagger = stagger % 4;
if (stagger === 0) {
ctx.lineTo(this.x2++, this.y2++);
ctx.stroke();
}
if (stagger === 1) {
ctx.lineTo(this.x3--, this.y3++);
ctx.stroke();
}
if (stagger === 2) {
ctx.lineTo(this.x4--, this.y4--);
ctx.stroke();
}
if (stagger === 3) {
ctx.lineTo(this.x1++, this.y1--);
ctx.stroke();
}
}
ctx.fill();
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 240) === 0) {
ctx.beginPath();
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.01, 0.01);
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.x4 = random(0, w);
this.y4 = random(0, h);
this.rotate = (random(4, 87) * Math.PI) / 180;
}
stagger++;
interval = requestAnimationFrame(this.draw);
};
}
}
class Smooth {
constructor() {
this.size = random(50, 500);
this.x = random(0, w);
this.y = random(0, h);
this.rot = random(1, 11);
ctx.fillStyle = randomColor(0, 255, 0.03, 0.08);
this.draw = () => {
if (t % speed === 0) {
ctx.fillRect(this.x, this.y, this.size, this.size);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 60) === 0) {
this.size = random(50, 500);
this.x = random(0, w);
this.y = random(0, h);
ctx.fillStyle = randomColor(0, 255, 0.03, 0.08);
this.rot = random(1, 11);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Glow {
constructor() {
this.margin1 = random(25, w / 4);
this.margin2 = random(25, w / 4);
this.color1 = randomColor(0, 255, 0.05, 0.2);
this.color2 = randomColor(0, 255, 0.05, 0.2);
this.rot = random(1, 60);
this.modes = ["color", "source-over", "overlay", "soft-light"];
ctx.strokeStyle = "white";
ctx.globalCompositeOperation = "color";
this.draw = () => {
if (t % speed === 0) {
ctx.fillStyle = this.color1;
ctx.fillRect(0, 0, w / 2 + this.margin1, h);
ctx.fillStyle = this.color2;
ctx.fillRect(w / 2 - this.margin2, 0, w, h);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 60) === 0) {
this.margin1 = random(25, w / 4);
this.color1 = randomColor(0, 255, 0.05, 0.2);
}
if (t % (speed * 90) === 0) {
this.margin2 = random(25, w / 4);
this.color2 = randomColor(0, 255, 0.05, 0.2);
}
if (t % (speed * 180) === 0) {
this.rot = random(1, 60);
ctx.globalCompositeOperation = this.modes[random(0, this.modes.length)];
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Encoded {
constructor() {
this.letters = ["S", "P", "I", "R", "A", "L"];
this.letter = this.letters[random(0, this.letters.length)];
this.size = random(100, 600);
this.rot = (random(1, 360) * Math.PI) / 180;
this.x = random(0, w);
this.y = random(0, h);
this.angles = [10, 12, 15, 18, 20, 24, 36, 45, 72];
this.angle = this.angles[random(0, this.angles.length)];
ctx.shadowColor = ctx.strokeStyle = randomColor(30, 255, 0.2, 0.6);
ctx.fillStyle = "rgba(0,0,0,0.2)";
ctx.font = `bold ${this.size}px serif`;
ctx.textAlign = "center";
ctx.shadowBlur = 10;
this.draw = () => {
if (t % speed === 0) {
ctx.strokeText(this.letter, this.x, this.y);
ctx.fillText(this.letter, this.x, this.y);
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.angle * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 72) === 0) {
this.letter = this.letters[random(0, this.letters.length)];
this.size = random(100, 600);
this.rot = (random(1, 360) * Math.PI) / 180;
ctx.shadowColor = ctx.strokeStyle = randomColor(30, 255, 0.2, 0.6);
ctx.font = `bold ${this.size}px serif`;
this.x = random(0, w);
this.y = random(0, h);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Concentric {
constructor() {
this.letters = [
2605,
2608,
2617,
2626,
2632,
2635,
2641,
2652,
2654,
2662,
2663,
2667,
2670,
2676,
2677,
2691,
2694,
2695,
2696,
2700
];
this.letter1 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter2 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter3 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter4 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.size = random(25, 160);
this.x = random(0, w);
this.y = random(0, h);
this.angles = [10, 12, 15, 18, 20, 24, 36, 45, 72];
this.angle = this.angles[random(0, this.angles.length)];
ctx.globalCompositeOperation = "soft-light";
ctx.shadowColor = ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor();
ctx.font = `bold ${this.size}px serif`;
ctx.textAlign = "center";
ctx.shadowBlur = 7;
ctx.lineWidth = 5;
this.draw = () => {
if (t % speed === 0) {
ctx.strokeText(
`${this.letter1} ${this.letter2} ${this.letter3} ${this.letter4}`,
this.x,
this.y
);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.angle);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 150) === 0) {
this.letter1 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter2 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter3 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter4 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.size = random(25, 160);
ctx.fillStyle = randomColor();
ctx.shadowColor = ctx.strokeStyle = randomColor(30, 255, 0.2, 0.6);
ctx.font = `bold ${this.size}px serif`;
this.x = random(0, w);
this.y = random(0, h);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Blends {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.length = random(30, 250);
this.shape1 = () =>
ctx.fillRect(this.x++, this.y, this.length++, this.length);
this.shape2 = () =>
ctx.arc(this.x2, this.y2++, this.length, 0, 2 * Math.PI);
this.shape3 = () => {
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x2, this.y2);
};
this.currentShape = random(0, 3);
this.rotation = random(2, 140);
this.color1 = randomColor(0, 255, 0.025, 0.075);
this.color2 = randomColor(0, 255, 0.025, 0.075);
ctx.lineWidth = 3;
ctx.strokeStyle = randomColor();
this.draw = () => {
if (t % speed === 0) {
if (this.currentShape === 0) {
ctx.fillStyle = this.color2;
this.shape1();
} else if (this.currentShape === 1) {
ctx.fillStyle = this.color1;
ctx.beginPath();
this.shape2();
ctx.fill();
} else {
ctx.strokeStyle = this.color2;
ctx.beginPath();
this.shape3();
ctx.stroke();
}
this.currentShape++;
if (this.currentShape > 2) this.currentShape = 0;
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotation * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
}
t++;
if (t % (speed * 270) === 0) {
this.rotation = random(2, 140);
this.x = random(0, w);
this.y = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.length = random(30, 250);
ctx.beginPath();
this.color1 = randomColor(0, 255, 0.025, 0.075);
this.color2 = randomColor(0, 255, 0.025, 0.075);
ctx.strokeStyle = randomColor();
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Matter {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.radius1 = random(5, 150);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.radius2 = random(5, 150);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.radius3 = random(5, 150);
this.rotate = random(10, 101);
ctx.fillStyle = randomColor(10, 255, 0.02, 0.07);
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x1, this.y1, this.radius1, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(this.x2, this.y2, this.radius2, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(this.x3, this.y3, this.radius3, 0, 2 * Math.PI);
ctx.fill();
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotate * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 120) === 0) {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.radius1 = random(5, 150);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.radius2 = random(5, 150);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.radius3 = random(5, 150);
ctx.fillStyle = randomColor(10, 255, 0.02, 0.07);
this.rotate = random(10, 101);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Seeds {
constructor() {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
this.rotate = random(10, 101);
ctx.fillStyle = ctx.strokeStyle = ctx.shadowColor = randomColor(
40,
255,
0.65,
1
);
ctx.shadowBlur = 2;
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x1++, this.y1--, 5, 0, 0.5 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.arc(this.x2--, this.y2++, 10, 0, 0.5 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.arc(this.x3++, this.y3, 15, 0, 0.5 * Math.PI);
ctx.stroke();
ctx.fill();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 360) === 0) {
this.x1 = random(0, w);
this.y1 = random(0, h);
this.x2 = random(0, w);
this.y2 = random(0, h);
this.x3 = random(0, w);
this.y3 = random(0, h);
ctx.fillStyle = ctx.strokeStyle = ctx.shadowColor = randomColor(
40,
255,
0.65,
1
);
this.rotate = random(10, 101);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Onion {
constructor() {
this.radius = random(45, 500);
this.x = random(0, w);
this.y = random(0, h);
this.angle = random(2, 50);
ctx.strokeStyle = "black";
ctx.fillStyle = randomColor(0, 255, 0.005, 0.015);
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.closePath();
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.angle / 180) * Math.PI);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 135) === 0) {
this.radius = random(50, 500);
this.x = random(0, w);
this.y = random(0, h);
ctx.beginPath();
ctx.fillStyle = randomColor(0, 255, 0.005, 0.015);
}
if (t % (speed * 540) === 0) {
this.angle = random(2, 50);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Spheral {
constructor() {
this.radius = random(50, 350);
this.x = random(0, w);
this.y = random(0, h);
this.angle = random(1, 90);
ctx.lineWidth = 2;
ctx.strokeStyle = ctx.shadowColor = randomColor();
ctx.shadowBlur = 2;
this.draw = () => {
if (t % speed === 0) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.angle / 180) * Math.PI);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 90) === 0) {
this.radius = random(50, 350);
this.x = random(0, w);
this.y = random(0, h);
ctx.beginPath();
}
if (t % (speed * 360) === 0) {
ctx.strokeStyle = ctx.shadowColor = randomColor();
}
interval = requestAnimationFrame(this.draw);
};
}
}
class SnakesLadders {
constructor() {
this.div = random(3, 17);
this.div2 = random(3, 17);
this.colSize = w / this.div;
this.rowSize = h / this.div2;
this.currCol = 0;
this.currRow = 0;
this.rotate = random(1, 83);
ctx.fillStyle = randomColor(0, 255, 0.15, 0.53);
ctx.strokeStyle = ctx.shadowColor = randomColor(0, 255, 0.55, 1);
ctx.shadowBlur = 3;
this.draw = () => {
if (t % speed === 0) {
ctx.strokeRect(
this.colSize * this.currCol,
this.rowSize * this.currRow,
this.colSize,
this.rowSize
);
this.currCol++;
if (this.currCol > this.div - 1) {
this.currCol = 0;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
this.currRow++;
if (this.currRow > this.div2 - 1) {
this.currRow = 0;
}
}
}
t++;
if (t % (speed * 720) === 0) {
ctx.fillRect(-w, -h, 3 * w, 3 * h);
this.rotate = random(1, 83);
this.div = random(3, 17);
this.div2 = random(3, 17);
this.colSize = w / this.div;
this.rowSize = h / this.div2;
ctx.beginPath();
ctx.fillStyle = randomColor(0, 255, 0.15, 0.53);
ctx.strokeStyle = ctx.shadowColor = randomColor(0, 255, 0.55, 1);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Cornucopia {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.width = random(15, 240);
this.height = random(15, 150);
this.ul = random(4, 35);
this.ur = random(4, 35);
this.dl = random(4, 35);
this.dr = random(4, 35);
this.rotate = random(1, 25);
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.025, 0.09);
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
this.x,
this.y,
this.width++,
this.height--,
{
upperLeft: this.ul--,
upperRight: this.ur++,
lowerLeft: this.dl++,
lowerRight: this.dr--
},
true,
false
);
}
t++;
if (t % (speed * 210) === 0) {
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.025, 0.09);
this.x = random(0, w);
this.y = random(0, h);
this.rotate = random(1, 25);
this.width = random(15, 240);
this.height = random(15, 150);
this.ul = random(4, 35);
this.ur = random(4, 35);
this.dl = random(4, 35);
this.dr = random(4, 35);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
interval = requestAnimationFrame(this.draw);
};
}
}
class Cornucopia2 {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.width = random(35, 440);
this.height = random(35, 350);
this.ul = random(4, 135);
this.ulc = random(-5, 5);
this.ur = random(4, 135);
this.urc = random(-5, 5);
this.dl = random(4, 135);
this.dlc = random(-5, 5);
this.dr = random(4, 135);
this.drc = random(-5, 5);
this.rotate = random(1, 75);
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor();
this.draw = () => {
if (t % speed === 0) {
ctx.roundRect(
this.x,
this.y,
this.width,
this.height,
{
upperLeft: this.ul,
upperRight: this.ur,
lowerLeft: this.dl,
lowerRight: this.dr
},
false,
true
);
this.ul += this.ulc;
this.ur += this.urc;
this.dl += this.dlc;
this.dr += this.drc;
}
t++;
if (t % (speed * 500) === 0) {
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor();
this.x = random(0, w);
this.y = random(0, h);
this.width = random(35, 440);
this.height = random(35, 350);
this.ul = random(4, 135);
this.ulc = random(-5, 5);
this.urc = random(-5, 5);
this.dlc = random(-5, 5);
this.drc = random(-5, 5);
this.ur = random(4, 135);
this.dl = random(4, 135);
this.dr = random(4, 135);
this.rotate = random(1, 75);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rotate);
ctx.translate(-w / 2, -h / 2);
interval = requestAnimationFrame(this.draw);
};
}
}
class Crosshatch {
constructor() {
this.x = random(0, w / 2);
this.y = random(0, h / 2);
this.length = random(32, 320);
this.rot = random(1, 30);
this.dash = random(5, 101);
ctx.lineWidth = 3;
ctx.strokeStyle = randomColor();
ctx.setLineDash([this.dash, this.dash]);
this.draw = () => {
if (t % speed === 0) {
ctx.strokeRect(this.x, this.y, this.length, this.length);
}
t++;
if (t % (speed * 120) === 0) {
this.x = random(0, w / 2);
this.y = random(0, h / 2);
this.length = random(32, 320);
}
if (t % (speed * 360) === 0) {
this.rot = random(1, 30);
this.dash = random(5, 101);
ctx.setLineDash([this.dash, this.dash]);
}
if (t % (speed * 720) === 0) {
ctx.clearRect(-w, -h, 3 * w, 3 * h);
ctx.beginPath();
ctx.strokeStyle = randomColor();
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
interval = requestAnimationFrame(this.draw);
};
}
}
class Networks {
constructor() {
this.drawAmount = 0.01;
this.x = random(0, w);
this.y = random(0, h);
this.rot = random(1, 71);
this.size = random(30, 200);
ctx.strokeStyle = randomColor();
this.draw = () => {
if (t % speed === 0) {
ctx.arc(this.x, this.y, this.size, 0, this.drawAmount * Math.PI * 2);
this.drawAmount += 0.0025;
this.size += 0.5;
ctx.stroke();
ctx.beginPath();
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 480) === 0) {
ctx.strokeStyle = randomColor();
this.drawAmount = 0.01;
this.x = random(0, w);
this.y = random(0, h);
this.rot = random(1, 71);
this.size = random(30, 200);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Spikral {
constructor() {
this.fillAmount = (Math.random() + 0.05) * (Math.PI / 2);
this.rot = random(1, 22);
this.size = random(20, 100);
ctx.fillStyle = randomColor(0, 255, 0.25, 1);
this.draw = () => {
if (t % speed === 0) {
ctx.arc(w / 2, h / 2, this.size, 0, this.fillAmount);
this.size *= 1.05;
ctx.fill();
ctx.beginPath();
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate(-this.rot);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 150) === 0) {
ctx.fillStyle = randomColor(0, 255, 0.25, 1);
this.fillAmount = (Math.random() + 0.05) * (Math.PI / 2);
this.size = random(20, 100);
}
if (t % (speed * 1500) === 0) {
this.rot = random(1, 22);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Fruits {
constructor() {
this.row = 0;
this.col = 0;
this.size = random(15, 105);
this.cell = 100;
ctx.strokeStyle = "black";
ctx.fillStyle = randomColor(0, 255, 0.1, 0.45);
this.draw = () => {
if (t % speed === 0) {
ctx.arc(
this.col * this.cell - this.cell,
this.row * this.cell - this.cell,
this.size,
0,
2 * Math.PI
);
ctx.stroke();
ctx.fill();
ctx.beginPath();
this.col++;
if (this.col * this.cell - this.cell * 2 > w) {
this.col = 0;
this.row++;
}
if (this.row * this.cell - this.cell * 2 > h) {
ctx.beginPath();
this.col = 0;
this.row = 0;
this.size = random(15, 105);
ctx.beginPath();
ctx.fillStyle = randomColor(0, 255, 0.1, 0.45);
}
}
t++;
interval = requestAnimationFrame(this.draw);
};
}
}
class Zentangles {
constructor() {
this.x = random(0, w);
this.xmod = random(-10, 11);
this.y = random(0, h);
this.ymod = random(-10, 11);
this.cpx = random(0, w);
this.cpxmod = random(-10, 11);
this.cpy = random(0, h);
this.cpymod = random(-10, 11);
this.rot = random(1, 360);
ctx.strokeStyle = randomColor(0, 255, 0.75, 1);
ctx.fillStyle = randomColor(0, 255, 0.1, 0.6);
ctx.lineWidth = 0.1;
ctx.moveTo(this.x, this.y);
ctx.fillRect(0, 0, w, h);
this.draw = () => {
if (t % speed === 0) {
ctx.quadraticCurveTo(this.cpx, this.cpy, this.x, this.y);
ctx.stroke();
this.x += this.xmod;
if (this.x < 0 || this.x > w) {
this.xmod = -this.xmod;
}
this.y += this.ymod;
if (this.y < 0 || this.y > h) {
this.ymod = -this.ymod;
}
this.cpx += this.cpxmod;
if (this.cpx < -2 * w || this.cpx > 2 * w) {
this.cpxmod = -this.cpxmod;
}
this.cpy += this.cpymod;
if (this.cpy < -2 * h || this.cpy > 2 * h) {
this.cpymod = -this.cpymod;
}
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rot * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 300) === 0) {
ctx.fillRect(-w, -h, 3 * w, 3 * h);
ctx.beginPath();
this.x = random(0, w);
this.xmod = random(-10, 11);
this.y = random(0, h);
this.ymod = random(-10, 11);
ctx.moveTo(this.x, this.y);
this.cpx = random(0, w);
this.cpxmod = random(-10, 11);
this.cpy = random(0, h);
this.cpymod = random(-10, 11);
this.rot = random(1, 360);
ctx.strokeStyle = randomColor(0, 255, 0.75, 1);
ctx.fillStyle = randomColor(0, 255, 0.1, 0.6);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Typobrush {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.letters = [
2703,
2705,
2709,
2713,
2715,
2716,
2718,
2719,
2720,
2721,
2722,
2725,
2726,
2731,
2732,
2735,
2738,
2739,
2741,
2742,
2743,
2745,
2748,
2750,
2751,
2752,
2753,
2760,
2764,
2768,
2784,
2791,
2792,
2795,
2796,
2797,
2798,
2799,
2800
];
this.letter = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.size = 20;
this.sizeInc = random(1, 6);
this.rot = random(1, 400);
ctx.strokeStyle = randomColor(0, 255, 0.33, 0.33);
ctx.fillStyle = "rgba(0, 0, 0, 0.75)";
ctx.textAlign = "center";
ctx.font = `${this.size}px serif`;
this.draw = () => {
if (t % speed === 0) {
ctx.strokeText(this.letter, this.x, this.y);
ctx.font = `${this.size}px serif`;
this.size += this.sizeInc;
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 150) === 0) {
this.size = 20;
ctx.font = `${this.size}px serif`;
this.x = random(0, w);
this.y = random(0, h);
this.rot = random(1, 400);
this.sizeInc = random(1, 6);
ctx.strokeStyle = randomColor(0, 255, 0.33, 0.33);
}
if (t % (speed * 1500) === 0) {
ctx.fillRect(-w, -h, 3 * w, 3 * h);
this.letter = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Veils {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.letters = [
2801,
2817,
2819,
2822,
2824,
2827,
2832,
2835,
2837,
2849,
2855,
2856,
2858,
2859,
2860,
2862,
2873,
2877,
2878,
2880,
2891,
2893
];
this.letter = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.rot = 1;
ctx.strokeStyle = randomColor(0, 255, 0.5, 0.5);
ctx.textAlign = "center";
this.size = random(30, 400);
ctx.font = `${this.size}px serif`;
this.draw = () => {
if (t % speed === 0) {
ctx.strokeText(this.letter, this.x, this.y);
this.size += 2;
ctx.font = `${this.size}px serif`;
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 540) === 0) {
this.letter = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.size = random(30, 400);
ctx.font = `${this.size}px serif`;
this.x = random(0, w);
this.y = random(0, h);
ctx.strokeStyle = randomColor(0, 255, 0.5, 0.5);
}
if (t % (speed * 1620) === 0) {
this.rot++;
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Harmonie {
constructor() {
this.x = random(0, w);
this.y = random(0, h);
this.letters = [
2902,
2908,
2909,
2911,
2913,
2915,
2918,
2919,
2921,
2922,
2924,
2925,
2926,
2927,
2928,
2929,
2930,
2931,
2932,
2934,
2938,
2947,
2949,
2952,
2953,
2960,
2962,
2970,
2972,
2975,
2980,
2984,
2986,
2990,
2991,
2992,
2994,
2997,
2998
];
this.letter1 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter2 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.size = random(20, 50);
this.rot = 23;
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor();
ctx.textAlign = "center";
ctx.font = `${this.size}px serif`;
this.draw = () => {
if (t % speed === 0) {
if (t % 2) {
ctx.strokeText(this.letter1, this.x, this.y);
} else {
ctx.fillText(this.letter2, this.x, this.y);
}
ctx.font = `${this.size}px serif`;
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rot * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 180) === 0) {
this.size = random(20, 50);
ctx.font = `${this.size}px serif`;
this.x = random(0, w);
this.y = random(0, h);
this.rot = random(1, 400);
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor();
}
if (t % (speed * 900) === 0) {
this.letter1 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
this.letter2 = String.fromCharCode(
this.letters[random(0, this.letters.length)]
);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Portals {
constructor() {
this.cols = random(3, 13);
this.rows = random(3, 13);
this.width = random(20, w / this.cols + 3);
this.height = random(20, w / this.rows + 3);
this.round = random(0, 60);
this.rot = random(1, 33);
ctx.strokeStyle = randomColor(0, 255, 1, 1);
ctx.globalCompositeOperation = "hard-light";
ctx.fillStyle = randomColor(0, 255, 0.4, 0.4);
ctx.globalAlpha = 0.5;
this.draw = () => {
if (t % speed === 0) {
for (let row = 0; row <= this.rows; row++) {
for (let col = 0; col <= this.cols; col++) {
ctx.roundRect(
col * (w / this.cols),
row * (h / this.rows),
this.width,
this.height,
{
upperLeft: this.round,
upperRight: this.round,
lowerLeft: this.round,
lowerRight: this.round
},
true,
true
);
}
}
}
t++;
if (t % (speed * 80) === 0) {
this.cols = random(3, 13);
this.rows = random(3, 13);
this.width = random(20, w / 8);
this.height = random(20, w / 8);
this.round = random(0, 60);
this.rot = random(1, 33);
ctx.strokeStyle = randomColor(0, 255, 1, 1);
ctx.fillStyle = randomColor(0, 255, 0.4, 0.4);
}
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
interval = requestAnimationFrame(this.draw);
};
}
}
class Sandala {
constructor() {
this.cols = random(5, 12);
this.rows = random(5, 12);
this.letters = [
3201,
3202,
3203,
3204,
3206,
3207,
3208,
3209,
3212,
3214,
3215,
3218,
3219,
3221,
3222,
3223,
3226,
3227,
3228,
3231,
3232,
3234,
3236,
3238,
3244,
3248,
3249,
3250,
3254,
3255,
3260,
3261,
3263,
3270,
3294,
3298
];
this.rot = random(1, 60);
ctx.strokeStyle = randomColor(0, 255, 1, 1);
ctx.globalCompositeOperation = "soft-light";
this.draw = () => {
if (t % speed === 0) {
for (let row = 0; row <= this.rows; row++) {
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rot * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
for (let col = 0; col <= this.cols; col++) {
ctx.strokeText(
String.fromCharCode(this.letters[random(0, this.letters.length)]),
row * (w / this.cols),
col * (h / this.rows)
);
}
}
}
t++;
if (t % (speed * 80) === 0) {
this.cols = random(5, 12);
this.rows = random(5, 12);
this.rot = random(1, 60);
ctx.strokeStyle = randomColor(0, 255, 1, 1);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class GhostlyShapes {
constructor() {
this.blends = [
"source-atop",
"lighter",
"xor",
"multiply",
"screen",
"overlay",
"darken",
"lighten",
"color-dodge",
"color-burn",
"hard-light",
"soft-light",
"difference",
"exclusion",
"hue",
"saturation",
"color",
"luminosity"
];
this.blend = this.blends[random(0, this.blends.length)];
this.cornersX = [0, w, w, 0];
this.cornersY = [0, 0, h, h];
this.cornerX = 0;
this.cornerY = 0;
this.rotation = random(1, 30);
this.radius = random(30, w);
ctx.fillStyle = randomColor(0, 255, 0.015, 0.05);
ctx.globalCompositeOperation = this.blend;
this.draw = () => {
if (t % speed === 0) {
ctx.arc(
this.cornersX[this.cornerX],
this.cornersY[this.cornerY],
this.radius,
Math.random(),
Math.random() * Math.PI,
true
);
this.cornerX =
this.cornerX + 1 >= this.cornersX.length ? 0 : this.cornerX + 1;
this.cornerY =
this.cornerY + 1 >= this.cornersY.length ? 0 : this.cornerY + 1;
ctx.fill();
ctx.beginPath();
}
t++;
if (t % (speed * 130) === 0) {
this.blend = this.blends[random(0, this.blends.length)];
ctx.globalCompositeOperation = this.blend;
this.radius = random(30, w);
this.rotation = random(1, 30);
ctx.beginPath();
ctx.strokeStyle = randomColor();
ctx.fillStyle = randomColor(0, 255, 0.015, 0.05);
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rotation * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
interval = requestAnimationFrame(this.draw);
};
}
}
class PsychoRainbow {
constructor() {
this.blends = ["hard-light", "difference", "color", "luminosity"];
this.blend = this.blends[random(0, this.blends.length)];
this.rows = random(3, 10);
this.rot = random(1, 50);
this.height = h / this.rows;
this.colors = [];
for (let i = 0; i <= this.rows; i++) {
this.colors.push(randomColor(0, 255, 0.1, 0.5));
}
ctx.globalCompositeOperation = this.blend;
this.draw = () => {
if (t % speed === 0) {
for (let i = 0; i <= this.rows; i++) {
ctx.fillStyle = this.colors[i];
ctx.fillRect(-w, i * this.height, 3 * w, this.height);
}
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 100) === 0) {
this.rows = random(3, 10);
this.rot = random(1, 50);
this.height = h / this.rows;
this.colors = [];
for (let i = 0; i <= this.rows; i++) {
this.colors.push(randomColor(0, 255, 0.1, 0.5));
}
}
if (t % (speed * 700) === 0) {
this.blend = this.blends[random(0, this.blends.length)];
ctx.globalCompositeOperation = this.blend;
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Hallucinate {
constructor() {
this.rows = random(3, 17);
this.rot = random(1, 180);
this.height = h / this.rows;
this.colors = [];
for (let i = 0; i <= this.rows; i++) {
this.colors.push(randomColor());
}
ctx.globalCompositeOperation = "soft-light";
this.draw = () => {
if (t % speed === 0) {
for (let i = 0; i <= this.rows; i++) {
ctx.fillStyle = this.colors[i];
ctx.fillRect(-w, i * this.height, 3 * w, this.height);
}
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate(this.rot);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 150) === 0) {
this.rows = random(3, 17);
this.rot = random(1, 180);
this.height = h / this.rows;
this.colors = [];
for (let i = 0; i <= this.rows; i++) {
this.colors.push(randomColor());
}
}
if (t % (speed * 750) === 0) {
ctx.clearRect(-w, -h, 3 * w, 3 * h);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Hive {
constructor() {
this.rows = random(3, 10);
this.height = h / this.rows;
this.angles = [9, 10, 12, 16, 20, 30, 36, 45, 60];
this.rot = this.angles[random(1, this.angles.length)];
ctx.globalCompositeOperation = "overlay";
ctx.strokeStyle = randomColor();
ctx.shadowColor = randomColor();
ctx.blur = 7;
ctx.lineWidth = random(7, 18);
this.draw = () => {
if (t % speed === 0) {
for (let i = 0; i <= this.rows; i++) {
ctx.strokeRect(
random(0, w),
i * this.height,
random(0, w),
this.height
);
}
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rot * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 125) === 0) {
ctx.shadowColor = randomColor();
this.rows = random(3, 10);
this.rot = this.angles[random(1, this.angles.length)];
this.height = h / this.rows;
ctx.strokeStyle = randomColor();
ctx.globalCompositeOperation = "overlay";
}
if (t % (speed * 500) === 0) {
ctx.globalCompositeOperation = "difference";
}
if (t % (speed * 1500) === 0) {
ctx.globalCompositeOperation = "hard-light";
}
interval = requestAnimationFrame(this.draw);
};
}
}
class Boxes {
constructor() {
this.rows = random(3, 17);
this.height = h / this.rows;
this.cols = random(3, 17);
this.width = w / this.cols;
this.angles = [15, 20, 24, 30, 36, 45, 48, 72, 80, 90];
this.rot = this.angles[random(0, this.angles.length)];
ctx.strokeStyle = "black";
ctx.fillStyle = randomColor(0, 255, 0.075, 0.075);
this.draw = () => {
if (t % speed === 0) {
for (let i = 0; i <= this.rows; i++) {
ctx.fillRect(
i * this.width,
i * this.height,
this.width / 2,
this.height / 2
);
ctx.strokeRect(
i * this.width,
i * this.height,
this.width / 2,
this.height / 2
);
}
}
t++;
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rot * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
if (t % (speed * 100) === 0) {
this.cols = random(3, 17);
this.width = w / this.cols;
this.rows = random(3, 17);
this.height = h / this.rows;
}
if (t % (speed * 200) === 0) {
this.rot = this.angles[random(0, this.angles.length)];
}
if (t % (speed * 400) === 0) {
ctx.fillStyle = randomColor(0, 255, 0.075, 0.075);
}
interval = requestAnimationFrame(this.draw);
};
}
}
class DigitalArt {
constructor() {
this.x = random(75, w - 75);
this.y = random(30, h - 30);
this.rot = random(3, 40);
this.size = random(12, 36);
ctx.font = `${this.size}px serif`;
ctx.fillStyle = randomColor();
this.draw = () => {
if (t % speed === 0) {
let letter = t % 2 ? "0" : "1";
if (t % 2) {
ctx.font = `${this.size * 2}px serif`;
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText(letter + "-", w / 2, h / 2);
} else {
ctx.font = `${this.size * 2}px serif`;
ctx.textAlign = "right";
ctx.textBaseline = "bottom";
ctx.fillText(letter + "_", w / 2, h / 2);
}
ctx.font = `${this.size}px serif`;
ctx.fillText(letter, this.x, this.y);
}
ctx.translate(w / 2, h / 2);
ctx.rotate((this.rot * Math.PI) / 180);
ctx.translate(-w / 2, -h / 2);
t++;
if (t % (speed * 90) === 0) {
this.x = random(75, w - 75);
this.y = random(30, h - 30);
this.size = random(12, 36);
ctx.font = `${this.size}px serif`;
ctx.fillStyle = randomColor();
}
if (t % (speed * 450) === 0) {
this.rot = random(3, 40);
}
interval = requestAnimationFrame(this.draw);
};
}
}
// END OF CLASSES
// initial setup of canvas settings and listeners
function init() {
// display some user tips on screen
displayMsg("WELCOME");
setTimeout(() => {
displayMsg("PRESS H FOR HELP");
}, 10000);
setTimeout(() => {
displayMsg("TIP: F FOR FULLSCREEN");
}, 20000);
// set the basic canvas settings
ctx.strokeStyle = randomColor(5, 255, 0.8, 0.8);
ctx.fillStyle = randomColor(5, 255, 0.5, 0.5);
ctx.imageSmoothingQuality = "high";
ctx.lineWidth = 1;
ctx.shadowBlur = 0;
ctx.save();
// LISTENERS
//change canvas size on window resize
window.addEventListener("resize", () => {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
canvas.click();
});
// keystroke listeners
window.addEventListener("keyup", (e) => {
// spacebar listener creates new spiral
if (e.keyCode === 32) {
canvas.click();
}
// f key for fullscreen
if (e.keyCode === 70) {
document.body.requestFullscreen();
}
// i key increases auto-change time
if (e.keyCode === 73) {
autoChange += 10;
if (autoChange > 300) autoChange = 300;
displayMsg(`Auto-change: ${autoChange}secs`);
}
// d key decreases auto-change time
if (e.keyCode === 68) {
autoChange -= 10;
if (autoChange < 10) autoChange = 10;
displayMsg(`Auto-change: ${autoChange}secs`);
}
// m key toggles manual mode
if (e.keyCode === 77) {
manual = !manual;
displayMsg(manual ? "Manual mode" : "Auto mode");
}
// s key silences algorithm change messages
if (e.keyCode === 83) {
silent = !silent;
displayMsg(silent ? "Silent mode" : "Display mode");
algosDisplay.textContent = "";
algosDisplay.style.display = "none";
}
// h key toggles help screen view
if (e.keyCode === 72) {
helpView = !helpView;
if (helpView) {
help.style.display = "block";
} else {
help.style.display = "none";
}
}
});
// make algorithms auto-change if not in manual mode
if (!manual) {
regen = setInterval(() => {
canvas.click();
}, autoChange * 1000);
}
}
// run init and start a random class spiral
init();
chooseAlgos();
// the click listener resets settings and draws a new spiral
canvas.addEventListener("click", () => {
// clear any timers
cancelAnimationFrame(interval);
interval = null;
clearInterval(regen);
t = 0;
stagger = 0;
// setup new auto-change timer if not in manual mode
if (!manual) {
regen = setInterval(() => {
canvas.click();
}, autoChange * 1000);
}
// new random speed
speed = random(2, 6);
// canvas resets
ctx.restore();
// picks a transition mode
canvas.style.backgroundColor = "transparent";
clearMethod();
ctx.strokeStyle = randomColor(5, 255, 0.8, 0.8);
ctx.fillStyle = randomColor(5, 255, 0.5, 0.5);
ctx.beginPath();
// selects next algorithm
chooseAlgos();
});
// helper function for random nums
function random(min, max) {
const num = Math.floor(Math.random() * (max - min)) + min;
return num;
}
// helper function for random colors
function randomColor(minC = 0, maxC = 255, minA = 1, maxA = minA) {
const r = random(minC, maxC);
const g = random(minC, maxC);
const b = random(minC, maxC);
const a = +(Math.random() * (maxA - minA) + minA).toFixed(3);
return `rgba(${r}, ${g}, ${b}, ${a})`;
}
// chooses a transition method when spirals change
function clearMethod() {
let pick = Math.random();
// clears to black a portion of the screen based on the canvas size and its rotation at the moment
if (pick < 0.25) {
ctx.clearRect(0, 0, w, h);
// makes semi-transparent a portion of the screen based on the canvas size and its rotation at the moment
} else if (pick < 0.5) {
ctx.fillStyle = "rgba(0, 0, 0, 0.75)";
ctx.fillRect(0, 0, w, h);
} else if (pick < 0.75) {
// colors a portion of the screen based on the canvas size and its rotation at the moment, with random transparency
ctx.fillStyle = randomColor(5, 255, 0.15, 0.9);
ctx.fillRect(0, 0, w, h);
// completely fills the screen with black
} else {
canvas.width = canvas.height = 0;
canvas.width = w;
canvas.height = h;
}
ctx.strokeStyle = randomColor(5, 255, 0.8, 0.8);
}
// displays the current algorithm on the screen for a few seconds when changing
function displayAlgos(algo) {
// only if silent mode is not on
if (!silent) {
clearTimeout(algoTimer);
algosDisplay.textContent = algo;
algosDisplay.style.display = "block";
algoTimer = setTimeout(() => {
algosDisplay.style.display = "none";
algosDisplay.textContent = "";
}, 5000);
}
}
// displays messages on the screen for a few seconds in response to user actions
function displayMsg(message) {
clearTimeout(msgTimer);
msg.textContent = message;
msg.style.display = "block";
msgTimer = setTimeout(() => {
msg.style.display = "none";
msg.textContent = "";
}, 7500);
}
let pointer;
canvas.addEventListener("mousemove", () => {
if (pointer) {
pointer = null;
}
canvas.style.cursor = "pointer";
pointer = setTimeout(() => {
canvas.style.cursor = "none";
}, 5000);
});
// MUSIC PLAYER
// DOM references
const player = document.getElementById("player");
const input = document.getElementById("input");
const label = document.getElementById("click-label");
const playList = document.getElementById("playlist");
const playBtn = document.getElementById("play");
const playIcon = document.getElementById("play-pause-icon");
const stopBtn = document.getElementById("stop");
const prevBtn = document.getElementById("prev");
const nextBtn = document.getElementById("next");
const audio = document.getElementById("audio");
const progress = document.getElementById("progress-percent");
// initial settings
let playerShow = true;
let trackList = [];
let currentSong = 0;
let isPlaying = false;
let playlistEls;
// listener for file input
input.addEventListener("change", handleFiles, false);
// handles the files and adds them to playlist
function handleFiles() {
// pause if playing and re-init settings
audio.pause();
isPlaying = false;
playIcon.name = "play-outline";
playList.innerHTML = "";
currentSong = 0;
trackList = [];
const files = this.files;
// add li for each song, create playlist
for (let i = 0; i < files.length; i++) {
let listItem = document.createElement("li");
listItem.classList.add("list-item");
listItem.textContent = files[i].name.slice(0, files[i].name.indexOf("."));
playList.appendChild(listItem);
let objectURL = window.URL.createObjectURL(files[i]);
trackList.push(objectURL);
}
let song = trackList[currentSong];
audio.src = song;
// style and prepare playlist for playback
playlistEls = document.getElementsByClassName("list-item");
playlistEls[currentSong].scrollIntoView();
playlistEls[currentSong].style.color = "rgba(255, 165, 0, 0.5)";
}
// play or pause current song
function playTrack() {
// if paused, play
if (!isPlaying && playlistEls) {
isPlaying = !isPlaying;
playIcon.name = "pause-outline";
updatePlaylistStyle();
audio.play();
} else {
// if playing, pause
if (playlistEls) {
isPlaying = !isPlaying;
playlistEls[currentSong].style.color = "rgba(255, 165, 0, 0.5)";
playIcon.name = "play-outline";
audio.pause();
}
}
}
// stop the track, rewind it and de-saturate color of li in playlist
function stopPlayback() {
if (isPlaying) {
audio.pause();
audio.currentTime = 0;
isPlaying = false;
playIcon.name = "play-outline";
[...playlistEls].forEach((el) => (el.style.color = "#555"));
playlistEls[currentSong].style.color = "rgba(255, 165, 0, 0.5)";
} else {
if (playlistEls) {
audio.currentTime = 0;
}
}
}
// cue the next track and play it if play is on
function playPrev() {
if (playlistEls) {
audio.pause();
audio.currentTime = 0;
progress.value = 0;
currentSong--;
if (currentSong < 0) currentSong = trackList.length - 1;
updatePlaylistStyle();
audio.src = trackList[currentSong];
if (isPlaying) {
audio.play();
} else {
playlistEls[currentSong].style.color = "rgba(255, 165, 0, 0.5)";
}
}
}
// cue the previous track and play it if play is on
function playNext() {
if (playlistEls) {
audio.pause();
audio.currentTime = 0;
progress.value = 0;
currentSong++;
if (currentSong > trackList.length - 1) currentSong = 0;
updatePlaylistStyle();
audio.src = trackList[currentSong];
if (isPlaying) {
audio.play();
} else {
playlistEls[currentSong].style.color = "rgba(255, 165, 0, 0.5)";
}
}
}
// calculates and displays the current track's progress
function displayProgress() {
const currentTime = audio.currentTime;
const progressPercent = (currentTime / audio.duration) * 100;
progress.value = Number.isFinite(progressPercent)
? progressPercent.toFixed(2)
: "0";
}
// skips to the clicked time on the progress bar
function scrub(e) {
if (playlistEls) {
const scrubTime = (e.offsetX / progress.offsetWidth) * audio.duration;
audio.currentTime = scrubTime;
if (isPlaying) {
audio.play();
}
}
}
// helper function for styling the playlist after changes
function updatePlaylistStyle() {
[...playlistEls].forEach((el) => (el.style.color = "#555"));
playlistEls[currentSong].style.color = "orange";
playlistEls[currentSong].scrollIntoView();
}
// music player event listeners
playBtn.addEventListener("click", playTrack);
stopBtn.addEventListener("click", stopPlayback);
nextBtn.addEventListener("click", playNext);
prevBtn.addEventListener("click", playPrev);
audio.addEventListener("timeupdate", displayProgress);
audio.addEventListener("ended", playNext);
progress.addEventListener("mousedown", () => audio.pause());
progress.addEventListener("mouseup", scrub);
window.addEventListener("keyup", hidePlayer);
// hide/show the player with the p key
function hidePlayer(e) {
if (e.keyCode === 80) {
if (playerShow) {
playerShow = !playerShow;
player.style.display = "none";
} else {
playerShow = !playerShow;
player.style.display = "block";
}
}
}
@import url("https://fonts.googleapis.com/css2?family=DM+Mono:wght@500&display=swap");
body {
background: black;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
font-family: "DM Mono", monospace;
letter-spacing: 2px;
font-size: 0.75em;
color: white;
text-shadow: 1px 1px black, -1px -1px black;
}
#canvas {
cursor: pointer;
}
/* HUD */
#hud {
background: transparent;
position: absolute;
text-align: right;
bottom: 2em;
right: 2.5em;
opacity: 0.7;
z-index: 1;
}
#help {
position: absolute;
z-index: 2;
opacity: 0.9;
background: rgba(0, 0, 0, 0.8);
padding: 1em;
font-family: "Oswald", sans-serif;
width: 75vw;
height: auto;
text-align: center;
pointer-events: none;
max-width: 600px;
display: none;
}
h1 {
margin-bottom: 0;
color: orangered;
font-size: 2.25em;
}
h4 {
margin-top: 0;
color: lightgray;
}
h3 {
margin-top: 0;
color: limegreen;
font-size: 1.4em;
}
p {
letter-spacing: 0;
}
.keys {
color: orange;
}
.text {
text-align: left;
}
.help {
color: limegreen;
font-size: 1.2em;
}
/* PLAYER */
input[type="file"] {
display: none;
}
#player {
background: #111;
display: block;
position: absolute;
top: 0;
width: 100vw;
overflow: hidden;
font-size: 1.15em;
font-family: "Oswald", sans-serif;
opacity: 0.7;
border-bottom-left-radius: 15px;
border-bottom-right-radius: 15px;
text-shadow: none;
}
#player:hover {
opacity: 1;
background: #171717;
}
#picker {
padding: 0 1em 0em 1em;
display: flex;
justify-content: space-between;
}
#picker label {
background: rgba(59, 136, 253, 0.8);
padding: 0.1em 0.5em;
margin-top: 0.5em;
font-size: 0.7em;
letter-spacing: 0.06em;
color: whitesmoke;
border-radius: 3px;
cursor: pointer;
align-self: center;
transition: all 0.2s;
}
#picker label:hover {
background: rgba(255, 69, 0, 0.6);
}
#playlist {
color: #999;
font-size: 0.9em;
padding: 0.25em 1em;
max-height: 22px;
overflow-y: scroll;
margin-bottom: 0.1em;
margin-left: 0.2em;
user-select: none;
}
#playlist li {
margin-top: 4px;
border-bottom: 1px dotted rgba(85, 85, 85, 0.4);
}
.list-item {
margin-left: 4px;
}
#controls {
text-align: center;
padding-top: 0.5em;
align-self: center;
}
#controls button {
color: orange;
font-size: 1.15em;
background: transparent;
border: 1px solid whitesmoke;
border-radius: 5px;
text-align: center;
line-height: 0.5;
cursor: pointer;
margin-right: 0.2em;
transition: all 0.2s;
outline: none;
}
#controls button:hover {
border-color: orangered;
color: whitesmoke;
}
progress {
margin: 0 auto;
width: 80%;
cursor: pointer;
display: block;
padding-bottom: 0.5em;
}
@media (max-width: 545px) {
#picker {
display: flex;
flex-direction: column;
}
#click-label {
position: absolute;
right: 1em;
}
#playlist {
display: inline;
text-align: center;
margin-bottom: 0;
font-size: 0.85em;
max-height: 17px;
}
#controls {
margin-top: 0;
padding-top: 0.2em;
margin-bottom: 5px;
}
#controls button {
font-size: 1em;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment