loop/node-server/assets/script.js
2025-06-07 07:00:55 +02:00

175 lines
4.4 KiB
JavaScript

// 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 calculer la vitesse de rotation
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) < 2) {
stopPlayback();
} else {
const isReverse = speed < 0;
// Simuler reverse
if (isReverse) {
simulateReverse(Math.abs(speed));
} else {
stopReverse();
let playbackSpeed = 1 + speed * 0.01;
playbackSpeed = Math.max(0.5, Math.min(2, playbackSpeed));
controlPlayback(playbackSpeed);
}
}
}
lastPosition = position;
lastTime = now;
// Détecter l'inactivité : si pas de mise à jour pendant 300ms → stop
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;
}
// Fonction pour régler la lecture selon la vitesse
function controlPlayback(speed) {
stopReverse(); // On stoppe le reverse si actif
if (speed > 0) {
if (!isPlaying) {
audio.play();
vinyl.style.animationPlayState = 'running';
isPlaying = true;
}
audio.playbackRate = speed;
}
}
function stopPlayback() {
audio.pause();
vinyl.style.animationPlayState = 'paused';
isPlaying = false;
}
function simulateReverse(speed) {
// vitesse = ticks/sec → convertir en vitesse de recul
const reverseSpeed = Math.min(speed * 0.01, 2); // seconds per step
if (!reverseInterval) {
reverseInterval = setInterval(() => {
if (audio.currentTime > 0.05) {
audio.currentTime -= reverseSpeed * 0.1;
vinyl.style.animationPlayState = 'running';
} else {
stopPlayback();
}
}, 100);
if (!isPlaying) {
isPlaying = true;
}
}
audio.pause(); // on met en pause le vrai son pour éviter conflit
}
function stopReverse() {
if (reverseInterval) {
clearInterval(reverseInterval);
reverseInterval = null;
}
}
// 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;
}
});