idk
This commit is contained in:
parent
9748e8b080
commit
2af94f3426
1 changed files with 144 additions and 72 deletions
216
index.html
216
index.html
|
|
@ -38,9 +38,10 @@ body { font-family:"Orbitron", sans-serif; background: var(--bg); color: var(--t
|
|||
.terminal-window .content::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 10px; }
|
||||
.terminal-window .content::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.3); }
|
||||
|
||||
/* Video container for pipes terminal */
|
||||
/* Visualizer canvas container */
|
||||
.video-container { width: 100%; height: 100%; position: relative; overflow: hidden; border-radius: 0 0 14px 14px; background: transparent; display: flex; align-items: center; justify-content: center; }
|
||||
.video-container video { width: 100%; height: 100%; object-fit: cover; display: block; background: transparent; }
|
||||
#vizCanvas { width: 100%; height: 100%; display: block; border-radius: 0 0 13px 13px; }
|
||||
.viz-idle-msg { position: absolute; color: rgba(255,255,255,0.22); font-size: 11px; letter-spacing: 2px; pointer-events: none; text-transform: uppercase; }
|
||||
|
||||
/* Loading screen */
|
||||
#loadingScreen {
|
||||
|
|
@ -251,8 +252,8 @@ body { font-family:"Orbitron", sans-serif; background: var(--bg); color: var(--t
|
|||
visualizer
|
||||
</div>
|
||||
<div class="video-container" id="pipesContainer">
|
||||
<div class="placeholder-text" id="pipesPlaceholder">Loading...</div>
|
||||
<video id="pipesVideo" autoplay loop muted playsinline style="display:none;"></video>
|
||||
<canvas id="vizCanvas"></canvas>
|
||||
<span class="viz-idle-msg" id="vizIdleMsg">play music to visualize</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -355,15 +356,12 @@ bgMusic.addEventListener('ended', () => {
|
|||
// Loading screen functionality
|
||||
const loadingScreen = document.getElementById('loadingScreen');
|
||||
const bgVideo = document.getElementById('bgVideo');
|
||||
const pipesVideo = document.getElementById('pipesVideo');
|
||||
const pipesPlaceholder = document.getElementById('pipesPlaceholder');
|
||||
|
||||
loadingScreen.addEventListener('click', () => {
|
||||
// Hide loading screen
|
||||
loadingScreen.classList.add('hidden');
|
||||
|
||||
// Start videos
|
||||
tryAutoLoad();
|
||||
// Load background video
|
||||
tryLoadBgVideo();
|
||||
|
||||
// Auto-play music
|
||||
setTimeout(() => {
|
||||
|
|
@ -379,77 +377,151 @@ loadingScreen.addEventListener('click', () => {
|
|||
}, 500);
|
||||
});
|
||||
|
||||
// Try to auto-load if videos are in same directory (fallback)
|
||||
async function tryAutoLoad() {
|
||||
try {
|
||||
const bgResponse = await fetch('backgroundVideo.mp4');
|
||||
if (bgResponse.ok) {
|
||||
const blob = await bgResponse.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
bgVideo.src = url;
|
||||
bgVideo.load();
|
||||
bgVideo.play().catch(e => console.error('BG video error:', e));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Background video not found, trying .webm');
|
||||
async function tryLoadBgVideo() {
|
||||
for (const name of ['backgroundVideo.mp4', 'backgroundVideo.webm']) {
|
||||
try {
|
||||
const bgResponse = await fetch('backgroundVideo.webm');
|
||||
if (bgResponse.ok) {
|
||||
const blob = await bgResponse.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
const res = await fetch(name);
|
||||
if (res.ok) {
|
||||
const url = URL.createObjectURL(await res.blob());
|
||||
bgVideo.src = url;
|
||||
bgVideo.load();
|
||||
bgVideo.play().catch(e => console.error('BG video error:', e));
|
||||
bgVideo.play().catch(() => {});
|
||||
return;
|
||||
}
|
||||
} catch (e2) {
|
||||
console.error('No background video found');
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Audio Visualizer ──────────────────────────────────────────────
|
||||
const vizCanvas = document.getElementById('vizCanvas');
|
||||
const vizCtx = vizCanvas.getContext('2d');
|
||||
const vizIdle = document.getElementById('vizIdleMsg');
|
||||
|
||||
let audioCtx, analyser, source, vizAnimId;
|
||||
let vizConnected = false;
|
||||
|
||||
function setupAnalyser() {
|
||||
if (vizConnected) return;
|
||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
analyser = audioCtx.createAnalyser();
|
||||
analyser.fftSize = 256;
|
||||
analyser.smoothingTimeConstant = 0.82;
|
||||
source = audioCtx.createMediaElementSource(bgMusic);
|
||||
source.connect(analyser);
|
||||
analyser.connect(audioCtx.destination);
|
||||
vizConnected = true;
|
||||
}
|
||||
|
||||
function resizeCanvas() {
|
||||
vizCanvas.width = vizCanvas.offsetWidth * devicePixelRatio;
|
||||
vizCanvas.height = vizCanvas.offsetHeight * devicePixelRatio;
|
||||
}
|
||||
|
||||
function drawViz() {
|
||||
vizAnimId = requestAnimationFrame(drawViz);
|
||||
resizeCanvas();
|
||||
|
||||
const W = vizCanvas.width, H = vizCanvas.height;
|
||||
const bufLen = analyser.frequencyBinCount;
|
||||
const data = new Uint8Array(bufLen);
|
||||
analyser.getByteFrequencyData(data);
|
||||
|
||||
// Clear with a slight fade trail for smoothness
|
||||
vizCtx.clearRect(0, 0, W, H);
|
||||
|
||||
const barCount = 80;
|
||||
const gap = W * 0.004;
|
||||
const barW = (W - gap * (barCount + 1)) / barCount;
|
||||
const step = Math.floor(bufLen / barCount);
|
||||
const maxH = H * 0.82;
|
||||
const baseY = H * 0.92;
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
// Average a small bucket for smoother freq representation
|
||||
let sum = 0;
|
||||
for (let k = 0; k < step; k++) sum += data[i * step + k];
|
||||
const avg = sum / step;
|
||||
const ratio = avg / 255;
|
||||
|
||||
const bh = ratio * maxH;
|
||||
const x = gap + i * (barW + gap);
|
||||
const y = baseY - bh;
|
||||
|
||||
// Bar opacity and glow scale with amplitude
|
||||
const alpha = 0.25 + ratio * 0.75;
|
||||
|
||||
// Subtle vertical gradient: bright top → dimmer base
|
||||
const grad = vizCtx.createLinearGradient(0, y, 0, baseY);
|
||||
grad.addColorStop(0, `rgba(255,255,255,${alpha})`);
|
||||
grad.addColorStop(0.6, `rgba(220,220,220,${alpha * 0.6})`);
|
||||
grad.addColorStop(1, `rgba(180,180,180,${alpha * 0.15})`);
|
||||
|
||||
vizCtx.fillStyle = grad;
|
||||
|
||||
// Rounded top on the bar
|
||||
const radius = Math.min(barW / 2, 4);
|
||||
vizCtx.beginPath();
|
||||
vizCtx.moveTo(x + radius, y);
|
||||
vizCtx.lineTo(x + barW - radius, y);
|
||||
vizCtx.quadraticCurveTo(x + barW, y, x + barW, y + radius);
|
||||
vizCtx.lineTo(x + barW, baseY);
|
||||
vizCtx.lineTo(x, baseY);
|
||||
vizCtx.lineTo(x, y + radius);
|
||||
vizCtx.quadraticCurveTo(x, y, x + radius, y);
|
||||
vizCtx.fill();
|
||||
|
||||
// Subtle glow on loud bars
|
||||
if (ratio > 0.5) {
|
||||
vizCtx.save();
|
||||
vizCtx.shadowColor = `rgba(255,255,255,${(ratio - 0.5) * 0.6})`;
|
||||
vizCtx.shadowBlur = 8 * ratio;
|
||||
vizCtx.fill();
|
||||
vizCtx.restore();
|
||||
}
|
||||
|
||||
// Floating dot cap above bar
|
||||
if (bh > 4) {
|
||||
vizCtx.fillStyle = `rgba(255,255,255,${alpha * 0.9})`;
|
||||
vizCtx.fillRect(x, y - 3, barW, 2);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const pipesResponse = await fetch('terminal.mp4');
|
||||
if (pipesResponse.ok) {
|
||||
const blob = await pipesResponse.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
pipesVideo.src = url;
|
||||
pipesVideo.style.display = 'block';
|
||||
pipesPlaceholder.style.display = 'none';
|
||||
pipesVideo.load();
|
||||
pipesVideo.play().catch(e => console.error('Pipes video error:', e));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Pipes video not found, trying .webm or pipes.mp4');
|
||||
try {
|
||||
const pipesResponse = await fetch('terminal.webm');
|
||||
if (pipesResponse.ok) {
|
||||
const blob = await pipesResponse.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
pipesVideo.src = url;
|
||||
pipesVideo.style.display = 'block';
|
||||
pipesPlaceholder.style.display = 'none';
|
||||
pipesVideo.load();
|
||||
pipesVideo.play().catch(e => console.error('Pipes video error:', e));
|
||||
}
|
||||
} catch (e2) {
|
||||
// Try pipes.mp4 as fallback
|
||||
try {
|
||||
const pipesResponse = await fetch('pipes.mp4');
|
||||
if (pipesResponse.ok) {
|
||||
const blob = await pipesResponse.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
pipesVideo.src = url;
|
||||
pipesVideo.style.display = 'block';
|
||||
pipesPlaceholder.style.display = 'none';
|
||||
pipesVideo.load();
|
||||
pipesVideo.play().catch(e => console.error('Pipes video error:', e));
|
||||
}
|
||||
} catch (e3) {
|
||||
console.error('No pipes video found');
|
||||
pipesPlaceholder.textContent = 'No video found';
|
||||
}
|
||||
}
|
||||
}
|
||||
// Baseline rule
|
||||
vizCtx.strokeStyle = 'rgba(255,255,255,0.08)';
|
||||
vizCtx.lineWidth = 1;
|
||||
vizCtx.beginPath();
|
||||
vizCtx.moveTo(0, baseY);
|
||||
vizCtx.lineTo(W, baseY);
|
||||
vizCtx.stroke();
|
||||
}
|
||||
|
||||
function startViz() {
|
||||
setupAnalyser();
|
||||
if (audioCtx.state === 'suspended') audioCtx.resume();
|
||||
vizIdle.style.opacity = '0';
|
||||
cancelAnimationFrame(vizAnimId);
|
||||
drawViz();
|
||||
}
|
||||
|
||||
function stopViz() {
|
||||
cancelAnimationFrame(vizAnimId);
|
||||
// Draw flat line when paused
|
||||
resizeCanvas();
|
||||
const W = vizCanvas.width, H = vizCanvas.height;
|
||||
vizCtx.clearRect(0, 0, W, H);
|
||||
vizCtx.strokeStyle = 'rgba(255,255,255,0.1)';
|
||||
vizCtx.lineWidth = 1;
|
||||
vizCtx.beginPath();
|
||||
vizCtx.moveTo(0, H * 0.92);
|
||||
vizCtx.lineTo(W, H * 0.92);
|
||||
vizCtx.stroke();
|
||||
vizIdle.style.opacity = '1';
|
||||
}
|
||||
|
||||
// Hook into existing play/pause logic
|
||||
bgMusic.addEventListener('play', () => startViz());
|
||||
bgMusic.addEventListener('pause', () => stopViz());
|
||||
bgMusic.addEventListener('ended', () => stopViz());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue