Auto commit: 2026-02-16T19:18:16.557Z
This commit is contained in:
parent
26bb9de84f
commit
80682f7095
257
index.php
257
index.php
@ -59,6 +59,8 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
height: 100%;
|
||||
background: url('assets/images/background.jpg') center/cover no-repeat;
|
||||
z-index: -1;
|
||||
transition: filter 0.1s ease-out, transform 0.1s ease-out;
|
||||
will-change: filter, transform;
|
||||
}
|
||||
|
||||
.background::after {
|
||||
@ -817,7 +819,7 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script>
|
||||
<audio id="radio-audio" src="https://listen.radioking.com/radio/828046/stream/897251" preload="none" crossorigin="anonymous"></audio>
|
||||
<audio id="radio-audio" src="https://listen.radioking.com/radio/828046/stream/897251" preload="auto" crossorigin="anonymous"></audio>
|
||||
<audio id="welcome-sound" src="https://assets.mixkit.co/active_storage/sfx/2013/2013-preview.mp3" preload="auto"></audio>
|
||||
|
||||
<script>
|
||||
@ -836,134 +838,161 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
let visualizerPeaks = [];
|
||||
let barHeights = new Array(BAR_COUNT).fill(5);
|
||||
let peakHeights = new Array(BAR_COUNT).fill(5);
|
||||
const bg = document.querySelector('.background');
|
||||
|
||||
function initVisualizer() {
|
||||
if (audioCtx) return;
|
||||
|
||||
// Create bars and peaks
|
||||
visualizerContainer.innerHTML = '';
|
||||
visualizerBars = [];
|
||||
visualizerPeaks = [];
|
||||
barHeights = new Array(BAR_COUNT).fill(5);
|
||||
peakHeights = new Array(BAR_COUNT).fill(5);
|
||||
|
||||
for (let i = 0; i < BAR_COUNT; i++) {
|
||||
const barWrapper = document.createElement('div');
|
||||
barWrapper.style.position = 'relative';
|
||||
barWrapper.style.height = '100%';
|
||||
barWrapper.style.display = 'flex';
|
||||
barWrapper.style.alignItems = 'flex-end';
|
||||
barWrapper.style.width = '18px';
|
||||
|
||||
const bar = document.createElement('div');
|
||||
bar.className = 'visualizer-bar';
|
||||
|
||||
const peak = document.createElement('div');
|
||||
peak.className = 'visualizer-peak';
|
||||
|
||||
barWrapper.appendChild(bar);
|
||||
barWrapper.appendChild(peak);
|
||||
visualizerContainer.appendChild(barWrapper);
|
||||
|
||||
visualizerBars.push(bar);
|
||||
visualizerPeaks.push(peak);
|
||||
let colorOffset = 0;
|
||||
function draw() {
|
||||
if (audio.paused || audio.ended) {
|
||||
animationId = null;
|
||||
visualizerBars.forEach(bar => bar.style.height = '5px');
|
||||
visualizerPeaks.forEach(peak => {
|
||||
peak.style.bottom = '5%';
|
||||
peak.style.background = 'linear-gradient(to bottom, #fff, transparent)';
|
||||
peak.style.boxShadow = '0 -2px 10px rgba(255, 255, 255, 0.8)';
|
||||
});
|
||||
document.documentElement.style.setProperty('--dynamic-glow', 'rgba(56, 189, 248, 0.7)');
|
||||
document.documentElement.style.setProperty('--dynamic-glow-dim', 'rgba(56, 189, 248, 0.4)');
|
||||
if (bg) {
|
||||
bg.style.filter = 'brightness(1)';
|
||||
bg.style.transform = 'scale(1)';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
analyzer = audioCtx.createAnalyser();
|
||||
source = audioCtx.createMediaElementSource(audio);
|
||||
source.connect(analyzer);
|
||||
analyzer.connect(audioCtx.destination);
|
||||
|
||||
analyzer.fftSize = 128;
|
||||
animationId = requestAnimationFrame(draw);
|
||||
const bufferLength = analyzer.frequencyBinCount;
|
||||
const dataArray = new Uint8Array(bufferLength);
|
||||
analyzer.getByteFrequencyData(dataArray);
|
||||
|
||||
let colorOffset = 0;
|
||||
function draw() {
|
||||
if (audio.paused) {
|
||||
visualizerBars.forEach(bar => bar.style.height = '5px');
|
||||
visualizerPeaks.forEach(peak => {
|
||||
peak.style.bottom = '5%';
|
||||
peak.style.background = 'linear-gradient(to bottom, #fff, transparent)';
|
||||
peak.style.boxShadow = '0 -2px 10px rgba(255, 255, 255, 0.8)';
|
||||
});
|
||||
document.documentElement.style.setProperty('--dynamic-glow', 'rgba(56, 189, 248, 0.7)');
|
||||
document.documentElement.style.setProperty('--dynamic-glow-dim', 'rgba(56, 189, 248, 0.4)');
|
||||
return;
|
||||
}
|
||||
animationId = requestAnimationFrame(draw);
|
||||
analyzer.getByteFrequencyData(dataArray);
|
||||
colorOffset += 1;
|
||||
|
||||
colorOffset += 1;
|
||||
|
||||
for (let i = 0; i < BAR_COUNT; i++) {
|
||||
// Map frequency data to bars
|
||||
const freqIndex = Math.floor((i / BAR_COUNT) * (dataArray.length * 0.8));
|
||||
const val = dataArray[freqIndex];
|
||||
const targetHeight = (val / 255) * 100 + 5;
|
||||
|
||||
// Retro "slow fall" logic
|
||||
if (targetHeight > barHeights[i]) {
|
||||
barHeights[i] = targetHeight; // Subida instantánea
|
||||
} else {
|
||||
barHeights[i] -= 1.5; // Caída lenta (decay)
|
||||
if (barHeights[i] < 5) barHeights[i] = 5;
|
||||
}
|
||||
|
||||
if (visualizerBars[i]) {
|
||||
visualizerBars[i].style.height = `${barHeights[i]}%`;
|
||||
}
|
||||
|
||||
// Peak logic
|
||||
if (barHeights[i] > peakHeights[i]) {
|
||||
peakHeights[i] = barHeights[i];
|
||||
} else {
|
||||
peakHeights[i] -= 0.8; // Peak falls even slower
|
||||
if (peakHeights[i] < 5) peakHeights[i] = 5;
|
||||
}
|
||||
|
||||
if (visualizerPeaks[i]) {
|
||||
visualizerPeaks[i].style.bottom = `${peakHeights[i]}%`;
|
||||
|
||||
// Color dinámico basado en la intensidad (altura del pico)
|
||||
// De 200 (Cian/Azul) en 0% a 0 (Rojo/Naranja) en 100%
|
||||
const hue = Math.max(0, 200 - (peakHeights[i] * 1.8));
|
||||
const color = `hsla(${hue}, 100%, 85%, 1)`;
|
||||
const glow = `hsla(${hue}, 100%, 60%, 0.9)`;
|
||||
|
||||
visualizerPeaks[i].style.background = `linear-gradient(to bottom, ${color}, transparent)`;
|
||||
visualizerPeaks[i].style.boxShadow = `0 -2px 12px ${glow}, 0 0 20px ${glow}`;
|
||||
|
||||
// Efecto Strobe en niveles críticos (> 90%) para un look agresivo
|
||||
if (peakHeights[i] > 90) {
|
||||
visualizerPeaks[i].classList.add('strobe');
|
||||
visualizerPeaks[i].style.setProperty('--peak-glow', glow);
|
||||
} else {
|
||||
visualizerPeaks[i].classList.remove('strobe');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic glow effect based on average volume
|
||||
let sum = 0;
|
||||
for(let i=0; i<dataArray.length; i++) sum += dataArray[i];
|
||||
const average = sum / dataArray.length;
|
||||
const dominantHue = (average * 2 + colorOffset) % 360;
|
||||
document.documentElement.style.setProperty('--dynamic-glow', `hsla(${dominantHue}, 100%, 60%, 0.8)`);
|
||||
document.documentElement.style.setProperty('--dynamic-glow-dim', `hsla(${dominantHue}, 100%, 60%, 0.3)`);
|
||||
// Bass detection for background flicker
|
||||
// We use the first 4 bins (low frequencies)
|
||||
const bassAvg = (dataArray[0] + dataArray[1] + dataArray[2] + dataArray[3]) / 4;
|
||||
const bassIntensity = bassAvg / 255;
|
||||
|
||||
// Apply flicker to background
|
||||
if (bg) {
|
||||
const brightness = 1 + (bassIntensity * 0.4); // More punchy
|
||||
const scale = 1 + (bassIntensity * 0.02);
|
||||
bg.style.filter = `brightness(${brightness})`;
|
||||
bg.style.transform = `scale(${scale})`;
|
||||
}
|
||||
draw();
|
||||
|
||||
for (let i = 0; i < BAR_COUNT; i++) {
|
||||
// Map frequency data to bars (skipping very low and very high)
|
||||
const freqIndex = Math.floor((i / BAR_COUNT) * (dataArray.length * 0.7)) + 1;
|
||||
const val = dataArray[freqIndex];
|
||||
const targetHeight = (val / 255) * 100 + 5;
|
||||
|
||||
// Retro "slow fall" logic
|
||||
if (targetHeight > barHeights[i]) {
|
||||
barHeights[i] = targetHeight;
|
||||
} else {
|
||||
barHeights[i] -= 2;
|
||||
if (barHeights[i] < 5) barHeights[i] = 5;
|
||||
}
|
||||
|
||||
if (visualizerBars[i]) {
|
||||
visualizerBars[i].style.height = `${barHeights[i]}%`;
|
||||
}
|
||||
|
||||
// Peak logic
|
||||
if (barHeights[i] > peakHeights[i]) {
|
||||
peakHeights[i] = barHeights[i];
|
||||
} else {
|
||||
peakHeights[i] -= 1.2;
|
||||
if (peakHeights[i] < 5) peakHeights[i] = 5;
|
||||
}
|
||||
|
||||
if (visualizerPeaks[i]) {
|
||||
visualizerPeaks[i].style.bottom = `${peakHeights[i]}%`;
|
||||
|
||||
const hue = Math.max(0, 200 - (peakHeights[i] * 1.8));
|
||||
const color = `hsla(${hue}, 100%, 85%, 1)`;
|
||||
const glow = `hsla(${hue}, 100%, 60%, 0.9)`;
|
||||
|
||||
visualizerPeaks[i].style.background = `linear-gradient(to bottom, ${color}, transparent)`;
|
||||
visualizerPeaks[i].style.boxShadow = `0 -2px 12px ${glow}, 0 0 20px ${glow}`;
|
||||
|
||||
if (peakHeights[i] > 90) {
|
||||
visualizerPeaks[i].classList.add('strobe');
|
||||
visualizerPeaks[i].style.setProperty('--peak-glow', glow);
|
||||
} else {
|
||||
visualizerPeaks[i].classList.remove('strobe');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic glow effect based on average volume
|
||||
let sum = 0;
|
||||
for(let i=0; i<dataArray.length; i++) sum += dataArray[i];
|
||||
const average = sum / dataArray.length;
|
||||
const dominantHue = (average * 2 + colorOffset) % 360;
|
||||
document.documentElement.style.setProperty('--dynamic-glow', `hsla(${dominantHue}, 100%, 60%, 0.8)`);
|
||||
document.documentElement.style.setProperty('--dynamic-glow-dim', `hsla(${dominantHue}, 100%, 60%, 0.3)`);
|
||||
}
|
||||
|
||||
function togglePlay() {
|
||||
function initVisualizer() {
|
||||
// Create bars and peaks if not already created
|
||||
if (visualizerBars.length === 0) {
|
||||
visualizerContainer.innerHTML = '';
|
||||
for (let i = 0; i < BAR_COUNT; i++) {
|
||||
const barWrapper = document.createElement('div');
|
||||
barWrapper.style.position = 'relative';
|
||||
barWrapper.style.height = '100%';
|
||||
barWrapper.style.display = 'flex';
|
||||
barWrapper.style.alignItems = 'flex-end';
|
||||
barWrapper.style.width = '18px';
|
||||
|
||||
const bar = document.createElement('div');
|
||||
bar.className = 'visualizer-bar';
|
||||
|
||||
const peak = document.createElement('div');
|
||||
peak.className = 'visualizer-peak';
|
||||
|
||||
barWrapper.appendChild(bar);
|
||||
barWrapper.appendChild(peak);
|
||||
visualizerContainer.appendChild(barWrapper);
|
||||
|
||||
visualizerBars.push(bar);
|
||||
visualizerPeaks.push(peak);
|
||||
}
|
||||
}
|
||||
|
||||
if (!audioCtx) {
|
||||
try {
|
||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
analyzer = audioCtx.createAnalyser();
|
||||
source = audioCtx.createMediaElementSource(audio);
|
||||
source.connect(analyzer);
|
||||
analyzer.connect(audioCtx.destination);
|
||||
analyzer.fftSize = 128;
|
||||
} catch (e) {
|
||||
console.error("AudioContext error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (audioCtx && audioCtx.state === 'suspended') {
|
||||
audioCtx.resume();
|
||||
}
|
||||
|
||||
if (!animationId && !audio.paused) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
audio.addEventListener('play', () => {
|
||||
initVisualizer();
|
||||
});
|
||||
|
||||
function togglePlay() {
|
||||
if (audio.paused) {
|
||||
initVisualizer();
|
||||
audio.play();
|
||||
audio.play().then(() => {
|
||||
initVisualizer();
|
||||
}).catch(err => {
|
||||
console.error("Error playing audio:", err);
|
||||
});
|
||||
playIcon.classList.remove('bi-play-fill');
|
||||
playIcon.classList.add('bi-pause-fill');
|
||||
playBtn.classList.add('playing');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user