feat: Add 14 genre-focused visualizer shapes and presets
This commit is contained in:
1 parent
771dc7914c
commit
6a1801ed92
4 files changed
+416
No files matched your search
+156
@@ -651,6 +651,162 @@
|
||||
const r = 0.76 + 0.24 * Math.cos(6 * (i / count) * Math.PI * 2);
|
||||
verts.push({ x: Math.cos(theta) * r, y: Math.sin(theta) * r });
|
||||
}
|
||||
} else if (shape === 'lightning') {
|
||||
verts = [
|
||||
{ x: 0.18, y: -1.0 },
|
||||
{ x: -0.42, y: -0.08 },
|
||||
{ x: -0.06, y: -0.08 },
|
||||
{ x: -0.32, y: 1.0 },
|
||||
{ x: 0.42, y: 0.08 },
|
||||
{ x: 0.06, y: 0.08 }
|
||||
];
|
||||
} else if (shape === 'flame') {
|
||||
const count = 64;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const u = (i / count) * Math.PI * 2;
|
||||
const px = 0.78 * Math.sin(u) * Math.pow(Math.sin(u / 2), 0.75);
|
||||
const py = -Math.cos(u) * 0.95 - 0.05 * Math.cos(2 * u);
|
||||
verts.push({ x: px, y: py });
|
||||
}
|
||||
} else if (shape === 'skull') {
|
||||
verts = [
|
||||
{ x: 0, y: -0.95 },
|
||||
{ x: 0.38, y: -0.90 },
|
||||
{ x: 0.70, y: -0.68 },
|
||||
{ x: 0.84, y: -0.32 },
|
||||
{ x: 0.82, y: 0.0 },
|
||||
{ x: 0.62, y: 0.18 },
|
||||
{ x: 0.75, y: 0.38 },
|
||||
{ x: 0.48, y: 0.52 },
|
||||
{ x: 0.42, y: 0.88 },
|
||||
{ x: 0.20, y: 0.94 },
|
||||
{ x: 0, y: 0.95 },
|
||||
{ x: -0.20, y: 0.94 },
|
||||
{ x: -0.42, y: 0.88 },
|
||||
{ x: -0.48, y: 0.52 },
|
||||
{ x: -0.75, y: 0.38 },
|
||||
{ x: -0.62, y: 0.18 },
|
||||
{ x: -0.82, y: 0.0 },
|
||||
{ x: -0.84, y: -0.32 },
|
||||
{ x: -0.70, y: -0.68 },
|
||||
{ x: -0.38, y: -0.90 }
|
||||
];
|
||||
} else if (shape === 'crown') {
|
||||
verts = [
|
||||
{ x: 0, y: -0.95 },
|
||||
{ x: 0.24, y: -0.32 },
|
||||
{ x: 0.50, y: -0.80 },
|
||||
{ x: 0.66, y: -0.25 },
|
||||
{ x: 0.88, y: -0.65 },
|
||||
{ x: 0.82, y: 0.70 },
|
||||
{ x: 0.40, y: 0.75 },
|
||||
{ x: 0, y: 0.76 },
|
||||
{ x: -0.40, y: 0.75 },
|
||||
{ x: -0.82, y: 0.70 },
|
||||
{ x: -0.88, y: -0.65 },
|
||||
{ x: -0.66, y: -0.25 },
|
||||
{ x: -0.50, y: -0.80 },
|
||||
{ x: -0.24, y: -0.32 }
|
||||
];
|
||||
} else if (shape === 'crescent') {
|
||||
const count = 36;
|
||||
for (let i = 0; i <= count; i++) {
|
||||
const a = Math.PI * 1.5 - (i / count) * Math.PI;
|
||||
verts.push({ x: 0.92 * Math.cos(a) + 0.42, y: 0.92 * Math.sin(a) });
|
||||
}
|
||||
for (let i = 1; i < count; i++) {
|
||||
const phi = Math.PI * 0.5 - (i / count) * Math.PI;
|
||||
verts.push({ x: -0.36 * Math.cos(phi) + 0.42, y: 0.92 * Math.sin(phi) });
|
||||
}
|
||||
} else if (shape === 'infinity') {
|
||||
const count = 64;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const theta = (i / count) * Math.PI * 2;
|
||||
const r = 0.32 + 0.64 * Math.pow(Math.cos(theta), 2);
|
||||
verts.push({ x: Math.cos(theta) * r, y: Math.sin(theta) * r });
|
||||
}
|
||||
} else if (shape === 'eye') {
|
||||
const count = 32;
|
||||
for (let i = 0; i <= count; i++) {
|
||||
const t = i / count;
|
||||
verts.push({ x: -0.95 + 1.90 * t, y: -Math.sin(t * Math.PI) * 0.62 });
|
||||
}
|
||||
for (let i = count - 1; i > 0; i--) {
|
||||
const t = i / count;
|
||||
verts.push({ x: -0.95 + 1.90 * t, y: Math.sin(t * Math.PI) * 0.62 });
|
||||
}
|
||||
} else if (shape === 'gem') {
|
||||
verts = [
|
||||
{ x: -0.52, y: -0.85 },
|
||||
{ x: 0.52, y: -0.85 },
|
||||
{ x: 0.92, y: -0.32 },
|
||||
{ x: 0, y: 0.98 },
|
||||
{ x: -0.92, y: -0.32 }
|
||||
];
|
||||
} else if (shape === 'pick') {
|
||||
const count = 48;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const a = (i / count) * Math.PI * 2;
|
||||
const px = 0.80 * Math.cos(a) * (1.0 - 0.45 * Math.sin(a));
|
||||
const py = 0.92 * Math.sin(a);
|
||||
verts.push({ x: px, y: py });
|
||||
}
|
||||
} else if (shape === 'sun') {
|
||||
const n = 16;
|
||||
const step = Math.PI / n;
|
||||
const start = -Math.PI / 2;
|
||||
for (let i = 0; i < n * 2; i++) {
|
||||
const r = (i % 2 === 0) ? 1.0 : 0.72;
|
||||
const a = start + i * step;
|
||||
verts.push({ x: Math.cos(a) * r, y: Math.sin(a) * r });
|
||||
}
|
||||
} else if (shape === 'droplet') {
|
||||
const count = 48;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const u = (i / count) * Math.PI * 2;
|
||||
const px = 0.82 * Math.sin(u) * Math.sin(u / 2);
|
||||
const py = -Math.cos(u) * 0.90 - 0.05 * Math.cos(2 * u) + 0.05;
|
||||
verts.push({ x: px, y: py });
|
||||
}
|
||||
} else if (shape === 'hourglass') {
|
||||
verts = [
|
||||
{ x: -0.80, y: -0.92 },
|
||||
{ x: 0.80, y: -0.92 },
|
||||
{ x: 0.18, y: 0.0 },
|
||||
{ x: 0.80, y: 0.92 },
|
||||
{ x: -0.80, y: 0.92 },
|
||||
{ x: -0.18, y: 0.0 }
|
||||
];
|
||||
} else if (shape === 'butterfly') {
|
||||
verts = [
|
||||
{ x: 0, y: -0.75 },
|
||||
{ x: 0.22, y: -0.68 },
|
||||
{ x: 0.62, y: -0.88 },
|
||||
{ x: 0.95, y: -0.48 },
|
||||
{ x: 0.72, y: -0.10 },
|
||||
{ x: 0.38, y: -0.02 },
|
||||
{ x: 0.78, y: 0.35 },
|
||||
{ x: 0.55, y: 0.72 },
|
||||
{ x: 0.20, y: 0.62 },
|
||||
{ x: 0, y: 0.82 },
|
||||
{ x: -0.20, y: 0.62 },
|
||||
{ x: -0.55, y: 0.72 },
|
||||
{ x: -0.78, y: 0.35 },
|
||||
{ x: -0.38, y: -0.02 },
|
||||
{ x: -0.72, y: -0.10 },
|
||||
{ x: -0.95, y: -0.48 },
|
||||
{ x: -0.62, y: -0.88 },
|
||||
{ x: -0.22, y: -0.68 }
|
||||
];
|
||||
} else if (shape === 'hexagram') {
|
||||
const n = 6;
|
||||
const step = Math.PI / n;
|
||||
const start = -Math.PI / 2;
|
||||
for (let i = 0; i < n * 2; i++) {
|
||||
const r = (i % 2 === 0) ? 1.0 : 0.577;
|
||||
const a = start + i * step;
|
||||
verts.push({ x: Math.cos(a) * r, y: Math.sin(a) * r });
|
||||
}
|
||||
}
|
||||
|
||||
SHAPE_VERTICES_CACHE[shape] = verts;
|
||||
|
||||
@@ -371,6 +371,104 @@
|
||||
<span class="shape-label">Blume</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="lightning">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">⚡</span>
|
||||
<span class="shape-label">Blitz</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="flame">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">🔥</span>
|
||||
<span class="shape-label">Flamme</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="skull">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">💀</span>
|
||||
<span class="shape-label">Totenkopf</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="crown">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">👑</span>
|
||||
<span class="shape-label">Krone</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="crescent">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">🌙</span>
|
||||
<span class="shape-label">Halbmond</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="infinity">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">♾️</span>
|
||||
<span class="shape-label">Infinity</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="eye">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">👁️</span>
|
||||
<span class="shape-label">Cyber-Auge</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="gem">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">💎</span>
|
||||
<span class="shape-label">Diamant</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="pick">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">🎸</span>
|
||||
<span class="shape-label">Plektrum</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="sun">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">☀️</span>
|
||||
<span class="shape-label">Sonne</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="droplet">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">💧</span>
|
||||
<span class="shape-label">Tropfen</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="hourglass">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">⏳</span>
|
||||
<span class="shape-label">Sanduhr</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="butterfly">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">🦋</span>
|
||||
<span class="shape-label">Schmetterling</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="shape-card">
|
||||
<input type="radio" name="shapeType" value="hexagram">
|
||||
<div class="shape-card-inner">
|
||||
<span class="shape-icon">✡️</span>
|
||||
<span class="shape-label">Hexagramm</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "Heavy Metal Lightning",
|
||||
"icon": "⚡",
|
||||
"shapeType": "lightning",
|
||||
"showCover": true,
|
||||
"coverShape": "circle",
|
||||
"circleRadius": 160,
|
||||
"pulseIntensity": 0.65,
|
||||
"pulseDecay": 0.82,
|
||||
"showBorder": true,
|
||||
"borderWidth": 4,
|
||||
"borderColor": "#ffcc00",
|
||||
"showProgressRing": true,
|
||||
"progressRingColor": "#ff2200",
|
||||
"progressRingWidth": 4,
|
||||
"rotationSpeed": 0.8,
|
||||
"beatSpinImpulse": true,
|
||||
"showSpectrum": true,
|
||||
"spectrumMode": "radial_bars",
|
||||
"linearAlignment": "center_mirrored",
|
||||
"barCount": 96,
|
||||
"spectrumMaxHeight": 150,
|
||||
"barWidth": 4,
|
||||
"barSpacing": 8,
|
||||
"barCornerRadius": 1,
|
||||
"freqSensitivity": 1.4,
|
||||
"freqFocus": "bass_heavy",
|
||||
"mirrorSpectrum": true,
|
||||
"stereoSplit": true,
|
||||
"stereoMode": "split_hemisphere",
|
||||
"routePulse": "sub_bass",
|
||||
"routeParticles": "treble",
|
||||
"routeShake": "sub_bass",
|
||||
"bpmSync": false,
|
||||
"bpmValue": 140,
|
||||
"bpmSyncRotation": false,
|
||||
"bpmSyncGrid": false,
|
||||
"enableParticles": true,
|
||||
"particleType": "sparks",
|
||||
"particleCount": 120,
|
||||
"particleSpeed": 1.4,
|
||||
"particleWarp": 2.0,
|
||||
"enableGrid": true,
|
||||
"colorGrid": "#ff3300",
|
||||
"gridPerspective": 0.7,
|
||||
"gridAudioReactive": 0.6,
|
||||
"enableShake": true,
|
||||
"camShakeIntensity": 0.45,
|
||||
"enableGlitch": true,
|
||||
"rgbSplitIntensity": 0.25,
|
||||
"beatFlash": true,
|
||||
"enableBassZoom": true,
|
||||
"enableVhs": false,
|
||||
"vhsScanlineIntensity": 0.2,
|
||||
"vhsNoiseIntensity": 0.1,
|
||||
"vhsCrtCurvature": false,
|
||||
"enableAfterglow": true,
|
||||
"afterglowDecay": 0.75,
|
||||
"afterglowMode": "fire_amber",
|
||||
"colorMode": "gradient_3",
|
||||
"colorGrad1": "#ffcc00",
|
||||
"colorGrad2": "#ff3300",
|
||||
"colorGrad3": "#990000",
|
||||
"colorParticle": "#ffea88",
|
||||
"gradientStyle": "angular",
|
||||
"enableGlow": true,
|
||||
"glowIntensity": 0.9,
|
||||
"glowBlur": 28,
|
||||
"laserCore": true,
|
||||
"backgroundMode": "transparent",
|
||||
"showTextOverlay": true,
|
||||
"fontFamily": "'Outfit', sans-serif",
|
||||
"textPosition": "below_circle",
|
||||
"titleFontSize": 40,
|
||||
"artistFontSize": 24,
|
||||
"textPulseWithBeat": true,
|
||||
"textGlow": true,
|
||||
"titleColor": "#ffffff",
|
||||
"artistColor": "#ffcc00",
|
||||
"timecodeColor": "#ff4422"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "Midnight Crescent",
|
||||
"icon": "🌙",
|
||||
"shapeType": "crescent",
|
||||
"showCover": true,
|
||||
"coverShape": "circle",
|
||||
"circleRadius": 155,
|
||||
"pulseIntensity": 0.45,
|
||||
"pulseDecay": 0.85,
|
||||
"showBorder": true,
|
||||
"borderWidth": 4,
|
||||
"borderColor": "#00f0ff",
|
||||
"showProgressRing": true,
|
||||
"progressRingColor": "#bd00ff",
|
||||
"progressRingWidth": 4,
|
||||
"rotationSpeed": 0.6,
|
||||
"beatSpinImpulse": false,
|
||||
"showSpectrum": true,
|
||||
"spectrumMode": "smooth_wave",
|
||||
"linearAlignment": "center_mirrored",
|
||||
"barCount": 120,
|
||||
"spectrumMaxHeight": 120,
|
||||
"barWidth": 3,
|
||||
"barSpacing": 6,
|
||||
"barCornerRadius": 2,
|
||||
"freqSensitivity": 1.2,
|
||||
"freqFocus": "flat",
|
||||
"mirrorSpectrum": true,
|
||||
"stereoSplit": true,
|
||||
"stereoMode": "split_hemisphere",
|
||||
"routePulse": "sub_bass",
|
||||
"routeParticles": "treble",
|
||||
"routeShake": "sub_bass",
|
||||
"bpmSync": false,
|
||||
"bpmValue": 90,
|
||||
"bpmSyncRotation": false,
|
||||
"bpmSyncGrid": false,
|
||||
"enableParticles": true,
|
||||
"particleType": "starfield",
|
||||
"particleCount": 130,
|
||||
"particleSpeed": 0.8,
|
||||
"particleWarp": 1.8,
|
||||
"enableGrid": true,
|
||||
"colorGrid": "#6b11ff",
|
||||
"gridPerspective": 0.6,
|
||||
"gridAudioReactive": 0.4,
|
||||
"enableShake": false,
|
||||
"camShakeIntensity": 0.2,
|
||||
"enableGlitch": false,
|
||||
"rgbSplitIntensity": 0.15,
|
||||
"beatFlash": false,
|
||||
"enableBassZoom": true,
|
||||
"enableVhs": false,
|
||||
"vhsScanlineIntensity": 0.2,
|
||||
"vhsNoiseIntensity": 0.1,
|
||||
"vhsCrtCurvature": false,
|
||||
"enableAfterglow": true,
|
||||
"afterglowDecay": 0.82,
|
||||
"afterglowMode": "magenta_dream",
|
||||
"colorMode": "gradient_3",
|
||||
"colorGrad1": "#00f0ff",
|
||||
"colorGrad2": "#a020f0",
|
||||
"colorGrad3": "#ff007f",
|
||||
"colorParticle": "#aae7ff",
|
||||
"gradientStyle": "angular",
|
||||
"enableGlow": true,
|
||||
"glowIntensity": 0.85,
|
||||
"glowBlur": 26,
|
||||
"laserCore": true,
|
||||
"backgroundMode": "transparent",
|
||||
"showTextOverlay": true,
|
||||
"fontFamily": "'Outfit', sans-serif",
|
||||
"textPosition": "below_circle",
|
||||
"titleFontSize": 38,
|
||||
"artistFontSize": 22,
|
||||
"textPulseWithBeat": true,
|
||||
"textGlow": true,
|
||||
"titleColor": "#ffffff",
|
||||
"artistColor": "#00f0ff",
|
||||
"timecodeColor": "#ff007f"
|
||||
}
|
||||
Reference in new issue
Block a user