Auto commit: 2026-02-16T13:11:18.684Z
This commit is contained in:
parent
400e93e9fd
commit
cda90baa2e
109
index.php
109
index.php
@ -312,23 +312,44 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
|
||||
.visualizer-container {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
height: 120px;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
overflow: hidden;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: radial-gradient(circle at center, rgba(56, 189, 248, 0.1) 0%, transparent 70%);
|
||||
background: radial-gradient(circle at center, rgba(56, 189, 248, 0.05) 0%, transparent 70%);
|
||||
position: relative;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
#visualizer {
|
||||
.audio-visualizer {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: drop-shadow(0 0 8px rgba(0, 230, 118, 0.5));
|
||||
}
|
||||
|
||||
.visualizer-bar {
|
||||
width: 18px;
|
||||
height: 5px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
background: var(--primary-color);
|
||||
transition: height 0.05s ease;
|
||||
min-height: 5px;
|
||||
}
|
||||
|
||||
/* Colores vibrantes para las barras */
|
||||
.visualizer-bar:nth-child(5n+1) { background: linear-gradient(to top, #00e676, #69f0ae); }
|
||||
.visualizer-bar:nth-child(5n+2) { background: linear-gradient(to top, #38bdf8, #7dd3fc); }
|
||||
.visualizer-bar:nth-child(5n+3) { background: linear-gradient(to top, #facc15, #fde047); }
|
||||
.visualizer-bar:nth-child(5n+4) { background: linear-gradient(to top, #f472b6, #fb923c); }
|
||||
.visualizer-bar:nth-child(5n+5) { background: linear-gradient(to top, #818cf8, #a5b4fc); }
|
||||
|
||||
/* Playing Animations */
|
||||
body.is-playing .glass-card {
|
||||
animation: card-pulse 4s infinite ease-in-out;
|
||||
@ -657,7 +678,7 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
|
||||
<div class="radio-player">
|
||||
<div class="visualizer-container">
|
||||
<canvas id="visualizer"></canvas>
|
||||
<div id="audio-visualizer" class="audio-visualizer"></div>
|
||||
</div>
|
||||
<div class="now-playing">
|
||||
<i class="bi bi-broadcast"></i>
|
||||
@ -780,40 +801,42 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
const playBtn = document.getElementById('play-pause');
|
||||
const playIcon = document.getElementById('play-icon');
|
||||
const trackTitle = document.getElementById('track-title');
|
||||
const canvas = document.getElementById('visualizer');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const visualizerContainer = document.getElementById('audio-visualizer');
|
||||
|
||||
let audioCtx;
|
||||
let analyzer;
|
||||
let source;
|
||||
let animationId;
|
||||
let bars = [];
|
||||
const BAR_COUNT = 16;
|
||||
let visualizerBars = [];
|
||||
|
||||
function initVisualizer() {
|
||||
if (audioCtx) return;
|
||||
|
||||
// Create bars
|
||||
visualizerContainer.innerHTML = '';
|
||||
visualizerBars = [];
|
||||
for (let i = 0; i < BAR_COUNT; i++) {
|
||||
const bar = document.createElement('div');
|
||||
bar.className = 'visualizer-bar';
|
||||
visualizerContainer.appendChild(bar);
|
||||
visualizerBars.push(bar);
|
||||
}
|
||||
|
||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
analyzer = audioCtx.createAnalyser();
|
||||
source = audioCtx.createMediaElementSource(audio);
|
||||
source.connect(analyzer);
|
||||
analyzer.connect(audioCtx.destination);
|
||||
|
||||
analyzer.fftSize = 256;
|
||||
analyzer.fftSize = 128;
|
||||
const bufferLength = analyzer.frequencyBinCount;
|
||||
const dataArray = new Uint8Array(bufferLength);
|
||||
|
||||
function resizeCanvas() {
|
||||
canvas.width = canvas.offsetWidth * window.devicePixelRatio;
|
||||
canvas.height = canvas.offsetHeight * window.devicePixelRatio;
|
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||
}
|
||||
resizeCanvas();
|
||||
window.addEventListener('resize', resizeCanvas);
|
||||
|
||||
let colorOffset = 0;
|
||||
function draw() {
|
||||
if (audio.paused) {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
visualizerBars.forEach(bar => bar.style.height = '5px');
|
||||
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;
|
||||
@ -821,51 +844,23 @@ $facebook_link = "https://www.facebook.com/profile.php?id=61587890927489";
|
||||
animationId = requestAnimationFrame(draw);
|
||||
analyzer.getByteFrequencyData(dataArray);
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
colorOffset += 1;
|
||||
|
||||
const barCount = 40; // Número de barras fijas para un look más limpio
|
||||
const logicalWidth = canvas.width / window.devicePixelRatio;
|
||||
const logicalHeight = canvas.height / window.devicePixelRatio;
|
||||
const gap = 4;
|
||||
const barWidth = (logicalWidth / barCount) - gap;
|
||||
|
||||
colorOffset += 2;
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
// Mapear el índice de la barra a la frecuencia (usando una escala logarítmica para mejor visual)
|
||||
const frequencyIndex = Math.floor(Math.pow(i / barCount, 1.5) * (bufferLength / 2));
|
||||
const barHeight = (dataArray[frequencyIndex] / 255) * logicalHeight * 0.8 + 5;
|
||||
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 height = (val / 255) * 100 + 5;
|
||||
|
||||
const x = i * (barWidth + gap);
|
||||
const barHue = (colorOffset + (i / barCount) * 200) % 360;
|
||||
|
||||
const gradient = ctx.createLinearGradient(0, logicalHeight, 0, logicalHeight - barHeight);
|
||||
gradient.addColorStop(0, `hsla(${barHue}, 100%, 50%, 0.2)`);
|
||||
gradient.addColorStop(0.5, `hsla(${barHue}, 100%, 50%, 0.8)`);
|
||||
gradient.addColorStop(1, `hsla(${(barHue + 60) % 360}, 100%, 70%, 1)`);
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
|
||||
// Dibujar barra con bordes redondeados superiores
|
||||
ctx.beginPath();
|
||||
if (ctx.roundRect) {
|
||||
ctx.roundRect(x, logicalHeight - barHeight, barWidth, barHeight, [5, 5, 0, 0]);
|
||||
} else {
|
||||
ctx.rect(x, logicalHeight - barHeight, barWidth, barHeight);
|
||||
if (visualizerBars[i]) {
|
||||
visualizerBars[i].style.height = `${height}%`;
|
||||
}
|
||||
ctx.fill();
|
||||
|
||||
// Añadir un "cap" o punto brillante arriba de la barra
|
||||
ctx.fillStyle = `hsla(${(barHue + 60) % 360}, 100%, 80%, 1)`;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x + barWidth/2, logicalHeight - barHeight, barWidth/3, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Efecto de brillo dinámico en la tarjeta basado en el volumen medio
|
||||
// Dynamic glow effect based on average volume
|
||||
let sum = 0;
|
||||
for(let i=0; i<bufferLength; i++) sum += dataArray[i];
|
||||
const average = sum / bufferLength;
|
||||
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)`);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user