- Parametric effect engine: 23 shader families × palettes × variants (~2300 presets) with a filterable library and an effect sequence (auto-cycle by time or beat). - Effect categories: fractals/abstract, dancing silhouettes, SVG/Image source (loads any SVG/image as a recolourable audio-reactive effect; 50+ bundled CC0 SVGs), and VU-Meter (32-band spectrum bars, analogue needle, stereo LEDs). - Dual-window architecture: control panel + fullscreen output on an external display (reliable via simple-fullscreen); tabbed control UI (Audio, Effetti, Pad, Immagini, Testo, Registra, Schermo). - Audio: file playback + live input + output device selection, per-band visual EQ, audio playlist (reorder, hotkeys, per-track play/pause, repeat). - Pad bank: 5×4 launchpad with persistent assignments; pressing a pad stops the current. - Overlays: slideshow images (resizable), two freely positioned/resizable logos, scrolling ticker text. - MP4 recording of the composited output (visual + overlays + audio) via MediaRecorder + ffmpeg, with selectable aspect ratios (16:9, 9:16, 1:1, 4:3, 3:4, 21:9). - App icon (.icns) and dock icon; author Dj LuZa. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
113 lines
3.0 KiB
HTML
113 lines
3.0 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="utf-8"><style>html,body{margin:0;background:#000}</style></head>
|
|
<body>
|
|
<canvas id="c" width="1024" height="1024"></canvas>
|
|
<script>
|
|
const c = document.getElementById('c');
|
|
const g = c.getContext('2d');
|
|
const S = 1024, cx = S / 2, cy = S / 2;
|
|
|
|
function roundRect(x, y, w, h, r) {
|
|
g.beginPath();
|
|
g.moveTo(x + r, y);
|
|
g.arcTo(x + w, y, x + w, y + h, r);
|
|
g.arcTo(x + w, y + h, x, y + h, r);
|
|
g.arcTo(x, y + h, x, y, r);
|
|
g.arcTo(x, y, x + w, y, r);
|
|
g.closePath();
|
|
}
|
|
|
|
// --- Background squircle with gradient ---
|
|
const m = 56, r = 224;
|
|
const bg = g.createLinearGradient(0, 0, S, S);
|
|
bg.addColorStop(0, '#241253');
|
|
bg.addColorStop(0.5, '#120a2e');
|
|
bg.addColorStop(1, '#06060f');
|
|
roundRect(m, m, S - 2 * m, S - 2 * m, r);
|
|
g.fillStyle = bg;
|
|
g.fill();
|
|
|
|
// Clip subsequent drawing to the squircle.
|
|
g.save();
|
|
roundRect(m, m, S - 2 * m, S - 2 * m, r);
|
|
g.clip();
|
|
|
|
// Soft radial glow behind the ring.
|
|
const glow = g.createRadialGradient(cx, cy, 40, cx, cy, 520);
|
|
glow.addColorStop(0, 'rgba(120,90,255,0.45)');
|
|
glow.addColorStop(0.5, 'rgba(70,40,160,0.18)');
|
|
glow.addColorStop(1, 'rgba(0,0,0,0)');
|
|
g.fillStyle = glow;
|
|
g.fillRect(0, 0, S, S);
|
|
|
|
// --- Circular audio spectrum (equaliser ring) ---
|
|
const bars = 72;
|
|
const innerR = 250;
|
|
g.lineCap = 'round';
|
|
for (let i = 0; i < bars; i++) {
|
|
const a = (i / bars) * Math.PI * 2 - Math.PI / 2;
|
|
// Pseudo audio profile: layered sines for a lively waveform.
|
|
const v = 0.5
|
|
+ 0.30 * Math.sin(i * 0.55)
|
|
+ 0.18 * Math.sin(i * 1.7 + 1.2)
|
|
+ 0.12 * Math.sin(i * 0.27 + 2.5);
|
|
const len = 70 + Math.max(0, v) * 150;
|
|
const x1 = cx + Math.cos(a) * innerR;
|
|
const y1 = cy + Math.sin(a) * innerR;
|
|
const x2 = cx + Math.cos(a) * (innerR + len);
|
|
const y2 = cy + Math.sin(a) * (innerR + len);
|
|
const hue = (i / bars) * 360;
|
|
g.strokeStyle = 'hsl(' + hue + ', 95%, 62%)';
|
|
g.shadowColor = 'hsl(' + hue + ', 95%, 60%)';
|
|
g.shadowBlur = 22;
|
|
g.lineWidth = 14;
|
|
g.beginPath();
|
|
g.moveTo(x1, y1);
|
|
g.lineTo(x2, y2);
|
|
g.stroke();
|
|
}
|
|
g.shadowBlur = 0;
|
|
|
|
// --- Inner disc ---
|
|
const disc = g.createRadialGradient(cx - 60, cy - 70, 30, cx, cy, innerR);
|
|
disc.addColorStop(0, '#2a1b66');
|
|
disc.addColorStop(1, '#0b0820');
|
|
g.beginPath();
|
|
g.arc(cx, cy, innerR - 16, 0, Math.PI * 2);
|
|
g.fillStyle = disc;
|
|
g.fill();
|
|
g.lineWidth = 8;
|
|
g.strokeStyle = 'rgba(150,120,255,0.5)';
|
|
g.stroke();
|
|
|
|
// --- Play triangle (neon) ---
|
|
const tri = 120;
|
|
g.beginPath();
|
|
g.moveTo(cx - tri * 0.6 + 18, cy - tri);
|
|
g.lineTo(cx - tri * 0.6 + 18, cy + tri);
|
|
g.lineTo(cx + tri + 18, cy);
|
|
g.closePath();
|
|
const tg = g.createLinearGradient(cx - tri, cy - tri, cx + tri, cy + tri);
|
|
tg.addColorStop(0, '#5ad1ff');
|
|
tg.addColorStop(0.5, '#9a7bff');
|
|
tg.addColorStop(1, '#ff7ad1');
|
|
g.fillStyle = tg;
|
|
g.shadowColor = 'rgba(150,120,255,0.9)';
|
|
g.shadowBlur = 40;
|
|
g.fill();
|
|
g.shadowBlur = 0;
|
|
|
|
g.restore();
|
|
|
|
// Subtle inner stroke on the squircle edge.
|
|
roundRect(m, m, S - 2 * m, S - 2 * m, r);
|
|
g.lineWidth = 3;
|
|
g.strokeStyle = 'rgba(255,255,255,0.10)';
|
|
g.stroke();
|
|
|
|
window._iconReady = true;
|
|
</script>
|
|
</body>
|
|
</html>
|