// 1. Sélection des éléments du DOM const vinyl = document.getElementById('vinyl'); const audio = document.getElementById('audio'); const progress = document.getElementById('progress'); const currentTimeEl = document.getElementById('currentTime'); const durationEl = document.getElementById('duration'); const backwardBtn = document.getElementById('backward'); const forwardBtn = document.getElementById('forward'); const loopBtn = document.getElementById('loop'); // 2. Variables utiles let isPlaying = false; let isLooping = false; let idleTimeout = null; let reverseInterval = null; // 3. Variables pour calcul de vitesse let lastPosition = null; let lastTime = null; // 4. Connexion Socket.io const socket = io(); socket.on('position', (position) => { const now = Date.now(); if (lastPosition !== null && lastTime !== null) { const deltaPos = position - lastPosition; const deltaTime = (now - lastTime) / 1000; const speed = deltaPos / deltaTime; console.log('instant speed:', speed); clearTimeout(idleTimeout); if (Math.abs(speed) < 5) { stopPlayback(); return; } const isReverse = speed < 0; if (isReverse) { simulateReverse(Math.abs(speed)); } else { stopReverse(); controlPlayback(speed); } } lastPosition = position; lastTime = now; idleTimeout = setTimeout(() => { stopPlayback(); }, 300); }); // 5. Fonctions function togglePlay() { if (isPlaying) { audio.pause(); vinyl.style.animationPlayState = 'paused'; } else { audio.play(); vinyl.style.animationPlayState = 'running'; } isPlaying = !isPlaying; } function updateProgress() { const progressPercent = (audio.currentTime / audio.duration) * 100; progress.value = progressPercent; currentTimeEl.textContent = formatTime(audio.currentTime); } function formatTime(time) { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; } function setProgress(e) { const width = progress.clientWidth; const clickX = e.offsetX; const duration = audio.duration; audio.currentTime = (clickX / width) * duration; } // Lecture en avant selon la vitesse function controlPlayback(speed) { stopReverse(); if (speed > 0) { if (!isPlaying) { audio.play(); vinyl.style.animationPlayState = 'running'; isPlaying = true; } // Vitesse normalisée const normalized = Math.min(speed / 400, 1); const minRate = 0.3; const maxRate = 1.5; const playbackSpeed = minRate + (maxRate - minRate) * Math.pow(normalized, 1.2); audio.playbackRate = playbackSpeed; vinyl.style.animationDuration = `${1 / playbackSpeed * 2}s`; vinyl.style.animationDirection = 'normal'; } } function stopPlayback() { audio.pause(); vinyl.style.animationPlayState = 'paused'; isPlaying = false; stopReverse(); } function simulateReverse(speed) { const reverseSpeed = Math.min(speed * 0.03, 2); // secondes à reculer par tick if (!reverseInterval) { reverseInterval = setInterval(() => { if (audio.currentTime > 0.05) { audio.currentTime -= reverseSpeed * 0.1; vinyl.style.animationPlayState = 'running'; vinyl.style.animationDirection = 'reverse'; } else { stopPlayback(); } }, 100); if (!isPlaying) { isPlaying = true; } } audio.pause(); // son désactivé pour reverse simulé } function stopReverse() { if (reverseInterval) { clearInterval(reverseInterval); reverseInterval = null; vinyl.style.animationDirection = 'normal'; } } // 6. Événements vinyl.addEventListener('click', togglePlay); audio.addEventListener('timeupdate', updateProgress); audio.addEventListener('loadedmetadata', () => { durationEl.textContent = formatTime(audio.duration); }); progress.addEventListener('click', setProgress); backwardBtn.addEventListener('click', () => { audio.currentTime = Math.max(0, audio.currentTime - 10); }); forwardBtn.addEventListener('click', () => { audio.currentTime = Math.min(audio.duration, audio.currentTime + 10); }); loopBtn.addEventListener('click', () => { isLooping = !isLooping; loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent'; loopBtn.style.color = isLooping ? '#18344b' : 'white'; }); audio.addEventListener('ended', () => { if (isLooping) { audio.currentTime = 0; audio.play(); } else { vinyl.style.animationPlayState = 'paused'; isPlaying = false; } });