For the optimal experience,
please view this website
on a desktop computer.
* { box-sizing: border-box; margin: 0; padding: 0; } body { width: 100%; height: 100vh; overflow: hidden; } main { width: 100%; height: 100%; color: #fff; font-family: "Montserrat"; display: flex; flex-direction: column; justify-content: center; align-items: center; pointer-events: none; user-select: none; h1 { font-size: 1.15rem; } p { font-size: 0.85rem; text-align: center; } } #canvas-container { position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: -1; } .support{ position: absolute; right: 10px; bottom: 10px; padding: 10px; display: flex; a{ margin: 0 10px; color: #fff; font-size: 1.8rem; backface-visibility: hidden; transition: all 150ms ease; &:hover{ transform: scale(1.1); } } } console.clear(); // This was originally written on processing which was based on code from Keith Peters. const GUI = new dat.GUI(); const SETTINGS = { length: { value: 200, min: 50, max: 1000, }, segmentLength: { value: 5, min: 1, max: 50, }, strokeWidth: { value: 2, min: 1, max: 10, }, color: "#fff", rainbow: false, }; let cursor; function setup() { let canvas = createCanvas(innerWidth, innerHeight); canvas.parent("canvas-container"); reset(); } function reset() { if (SETTINGS.rainbow) colorMode(HSB); cursor = new Cursor({ length: SETTINGS.length.value, segmentLength: SETTINGS.segmentLength.value, color: SETTINGS.rainbow ? "rainbow" : SETTINGS.color, }); } function draw() { background(0); cursor.draw(); } function addGUI() { GUI.add(SETTINGS.length, "value", SETTINGS.length.min, SETTINGS.length.max).name("Length").step(1).onChange(reset); GUI.add(SETTINGS.segmentLength, "value", SETTINGS.segmentLength.min, SETTINGS.segmentLength.max) .name("Segment Length") .step(1) .onChange(reset); GUI.add(SETTINGS.strokeWidth, "value", SETTINGS.strokeWidth.min, SETTINGS.strokeWidth.max) .name("Stroke Width") .step(1) .onChange(reset); GUI.addColor(SETTINGS, "color").name("Color").onChange(reset); GUI.add(SETTINGS, "rainbow").name("Rainbow").onChange(reset); } addGUI(); function windowResized() { resizeCanvas(innerWidth, innerHeight); reset(); } // cursor class class Cursor { constructor(options = {}) { this.length = options.length || 100; this.color = options.color || color(255); this.segmentLength = options.segmentLength || 5; this.x = new Array(floor(this.length / this.segmentLength)).fill(0); this.y = new Array(floor(this.length / this.segmentLength)).fill(0); this.rainbowColors = ["#00f", "#70a", "#f00", "#f70", "#ff0", "#0f0"]; } draw() { if (this.color !== "rainbow") stroke(this.color); strokeWeight(SETTINGS.strokeWidth.value); this.dragSegment(0, mouseX, mouseY); for (let i = 0; i < this.x.length - 1; i++) { if (this.color === "rainbow") stroke(this.rainbowColors[i % this.rainbowColors.length]); this.dragSegment(i + 1, this.x[i], this.y[i]); } } dragSegment(i, xin, yin) { let dx = xin - this.x[i]; let dy = yin - this.y[i]; let angle = atan2(dy, dx); this.x[i] = xin - cos(angle) * this.segmentLength; this.y[i] = yin - sin(angle) * this.segmentLength; this.segment(this.x[i], this.y[i], angle); } segment(x, y, a) { push(); translate(x, y); rotate(a); line(0, 0, this.segmentLength, 0); pop(); } }