This commit is contained in:
El-yazide MOHAMED 2025-06-07 17:04:57 +02:00
parent 825acfe48b
commit 9cf7c74f9c

View File

@ -1,4 +1,4 @@
// 1. Sélection des éléments du DOM // 1. Sélection des éléments DOM
const vinyl = document.getElementById('vinyl'); const vinyl = document.getElementById('vinyl');
const audio = document.getElementById('audio'); const audio = document.getElementById('audio');
const progress = document.getElementById('progress'); const progress = document.getElementById('progress');
@ -12,13 +12,12 @@ const loopBtn = document.getElementById('loop');
let isPlaying = false; let isPlaying = false;
let isLooping = false; let isLooping = false;
let idleTimeout = null; let idleTimeout = null;
let reverseInterval = null;
// 3. Variables pour calcul de vitesse
let lastPosition = null; let lastPosition = null;
let lastTime = null; let lastTime = null;
// 4. Connexion Socket.io const rotationsPerTrack = 3; // Nombre de tours complets du vinyle sur toute la durée
// 3. Connexion Socket.io
const socket = io(); const socket = io();
socket.on('position', (position) => { socket.on('position', (position) => {
@ -28,35 +27,46 @@ socket.on('position', (position) => {
const deltaPos = position - lastPosition; const deltaPos = position - lastPosition;
const deltaTime = (now - lastTime) / 1000; const deltaTime = (now - lastTime) / 1000;
const speed = deltaPos / deltaTime; const speed = deltaPos / deltaTime; // vitesse de rotation
console.log('instant speed:', speed);
clearTimeout(idleTimeout); clearTimeout(idleTimeout);
// Si la vitesse est très faible, on considère que l'encodeur est à l'arrêt
if (Math.abs(speed) < 5) { if (Math.abs(speed) < 5) {
stopPlayback(); stopPlayback();
return; return;
} }
const isReverse = speed < 0; if (speed < 0) {
// Rotation inverse : on recule la timeline
if (isReverse) { audio.pause();
simulateReverse(Math.abs(speed)); isPlaying = false;
// On recule la timeline proportionnellement à la vitesse inversée, avec un facteur de sensibilité
audio.currentTime = Math.max(0, audio.currentTime + speed * 0.03); // speed<0 donc avance négative ici
} else { } else {
stopReverse(); // Rotation avant : on joue la piste et ajuste la vitesse
controlPlayback(speed); if (!isPlaying) {
audio.play();
isPlaying = true;
}
// Accélération adoucie : vitesse lente plus étendue, max 1.5x
let playbackSpeed = 0.5 + speed / 400;
playbackSpeed = Math.min(Math.max(playbackSpeed, 0.5), 1.5);
audio.playbackRate = playbackSpeed;
// On fait avancer le son naturellement
} }
} }
lastPosition = position; lastPosition = position;
lastTime = now; lastTime = now;
// Détecter l'inactivité (pas de mouvement > 300ms) : stoppe la lecture
idleTimeout = setTimeout(() => { idleTimeout = setTimeout(() => {
stopPlayback(); stopPlayback();
}, 300); }, 300);
}); });
// 5. Fonctions // 4. Fonctions
function togglePlay() { function togglePlay() {
if (isPlaying) { if (isPlaying) {
@ -70,9 +80,15 @@ function togglePlay() {
} }
function updateProgress() { function updateProgress() {
const progressPercent = (audio.currentTime / audio.duration) * 100; if (!isNaN(audio.duration)) {
progress.value = progressPercent; const progressPercent = (audio.currentTime / audio.duration) * 100;
currentTimeEl.textContent = formatTime(audio.currentTime); progress.value = progressPercent;
currentTimeEl.textContent = formatTime(audio.currentTime);
durationEl.textContent = formatTime(audio.duration);
// Mise à jour rotation vinyle synchronisée au temps courant
updateVinylRotation();
}
} }
function formatTime(time) { function formatTime(time) {
@ -88,67 +104,25 @@ function setProgress(e) {
audio.currentTime = (clickX / width) * duration; audio.currentTime = (clickX / width) * duration;
} }
// Lecture en avant selon la vitesse // Fonction pour stopper la lecture
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() { function stopPlayback() {
audio.pause(); audio.pause();
vinyl.style.animationPlayState = 'paused'; vinyl.style.animationPlayState = 'paused';
isPlaying = false; isPlaying = false;
stopReverse(); audio.playbackRate = 1;
} }
function simulateReverse(speed) { // Fonction qui fait tourner le vinyle selon la timeline audio
const reverseSpeed = Math.min(speed * 0.03, 2); // secondes à reculer par tick function updateVinylRotation() {
if (audio.duration && audio.currentTime >= 0) {
if (!reverseInterval) { // Calcul de l'angle en degrés
reverseInterval = setInterval(() => { // rotation proportionnelle au temps courant * nombre de rotations sur la piste
if (audio.currentTime > 0.05) { const rotationDegrees = (audio.currentTime / audio.duration) * 360 * rotationsPerTrack;
audio.currentTime -= reverseSpeed * 0.1; vinyl.style.transform = `rotate(${rotationDegrees}deg)`;
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 // 5. Événements
vinyl.addEventListener('click', togglePlay); vinyl.addEventListener('click', togglePlay);
audio.addEventListener('timeupdate', updateProgress); audio.addEventListener('timeupdate', updateProgress);