retour sensi -
This commit is contained in:
parent
2b54c71eae
commit
ac89ce77e6
@ -1,210 +1,176 @@
|
|||||||
// Récupération des éléments
|
// 1. Sélection des éléments du DOM
|
||||||
const audioForward = document.getElementById('audio');
|
|
||||||
const reverseSrc = audioForward.getAttribute('data-reverse-src');
|
|
||||||
const audioReverse = new Audio(reverseSrc);
|
|
||||||
|
|
||||||
const progress = document.getElementById('progress');
|
|
||||||
const currentTimeElem = document.getElementById('currentTime');
|
|
||||||
const durationElem = document.getElementById('duration');
|
|
||||||
|
|
||||||
const vinyl = document.getElementById('vinyl');
|
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');
|
||||||
|
|
||||||
const btnForward = document.getElementById('forward');
|
// 2. Variables utiles
|
||||||
const btnBackward = document.getElementById('backward');
|
|
||||||
const btnLoop = document.getElementById('loop');
|
|
||||||
|
|
||||||
let lastPosition = 0;
|
|
||||||
let isPlaying = false;
|
let isPlaying = false;
|
||||||
let currentDirection = 1; // 1 = forward, -1 = reverse
|
let isLooping = false;
|
||||||
|
let idleTimeout = null;
|
||||||
|
let reverseInterval = null;
|
||||||
|
|
||||||
// Variables pour arrêter le son si pas de mouvement
|
// 3. Variables pour calculer la vitesse de rotation
|
||||||
let stopTimeout = null;
|
let lastPosition = null;
|
||||||
const STOP_DELAY = 1000; // ms sans mouvement avant arrêt
|
let lastTime = null;
|
||||||
|
|
||||||
// Une fois les métadonnées chargées, on met la durée
|
// 4. Connexion Socket.io
|
||||||
audioForward.addEventListener('loadedmetadata', () => {
|
const socket = io();
|
||||||
durationElem.textContent = formatTime(audioForward.duration);
|
|
||||||
progress.max = 100;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Formatage temps en mm:ss
|
socket.on('position', (position) => {
|
||||||
function formatTime(seconds) {
|
const now = Date.now();
|
||||||
const m = Math.floor(seconds / 60);
|
|
||||||
const s = Math.floor(seconds % 60);
|
|
||||||
return `${m}:${s < 10 ? '0' + s : s}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour arrêter les audios
|
if (lastPosition !== null && lastTime !== null) {
|
||||||
function stopAudio() {
|
const deltaPos = position - lastPosition;
|
||||||
audioForward.pause();
|
const deltaTime = (now - lastTime) / 1000;
|
||||||
audioReverse.pause();
|
|
||||||
isPlaying = false;
|
|
||||||
vinyl.style.animationPlayState = 'paused';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Met à jour la barre de progression et le timer courant
|
const speed = deltaPos / deltaTime;
|
||||||
function updateProgress(currentTime, duration) {
|
console.log('instant speed:', speed);
|
||||||
const percent = (currentTime / duration) * 100;
|
|
||||||
progress.value = percent;
|
|
||||||
currentTimeElem.textContent = formatTime(currentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour synchroniser la position de reverse sur la base de forward
|
clearTimeout(idleTimeout);
|
||||||
function syncReversePosition() {
|
|
||||||
audioReverse.currentTime = audioForward.duration - audioForward.currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour synchroniser la position de forward sur la base de reverse
|
if (Math.abs(speed) < 15) {
|
||||||
function syncForwardPosition() {
|
stopPlayback();
|
||||||
audioForward.currentTime = audioReverse.duration - audioReverse.currentTime;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Gestion du slider pour contrôle manuel
|
|
||||||
progress.addEventListener('input', () => {
|
|
||||||
const seekTime = (progress.value / 100) * audioForward.duration;
|
|
||||||
audioForward.currentTime = seekTime;
|
|
||||||
audioReverse.currentTime = audioForward.duration - seekTime;
|
|
||||||
// Si pause, on reste en pause
|
|
||||||
if (!isPlaying) {
|
|
||||||
updateProgress(seekTime, audioForward.duration);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fonction principale pour gérer la lecture en fonction de la position de l'encodeur
|
|
||||||
function handlePosition(position) {
|
|
||||||
const speedFactor = 0.1; // ajuster la vitesse de lecture ici
|
|
||||||
const delta = position - lastPosition;
|
|
||||||
|
|
||||||
// Si pas de mouvement détecté (delta petit), on stoppe après un délai
|
|
||||||
if (Math.abs(delta) < 0.01) {
|
|
||||||
if (stopTimeout === null) {
|
|
||||||
stopTimeout = setTimeout(() => {
|
|
||||||
stopAudio();
|
|
||||||
stopTimeout = null;
|
|
||||||
}, STOP_DELAY);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// Mouvement détecté => clear timeout arrêt
|
|
||||||
if (stopTimeout !== null) {
|
|
||||||
clearTimeout(stopTimeout);
|
|
||||||
stopTimeout = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcul vitesse lecture
|
|
||||||
let playbackRate = Math.min(Math.abs(delta) * speedFactor, 2); // max 2x vitesse
|
|
||||||
|
|
||||||
if (delta > 0) {
|
|
||||||
// Lecture forward
|
|
||||||
if (currentDirection !== 1) {
|
|
||||||
// Switch direction: garder la position
|
|
||||||
audioForward.currentTime = audioReverse.duration - audioReverse.currentTime;
|
|
||||||
audioReverse.pause();
|
|
||||||
currentDirection = 1;
|
|
||||||
}
|
|
||||||
if (audioForward.paused) audioForward.play();
|
|
||||||
audioForward.playbackRate = playbackRate;
|
|
||||||
audioReverse.pause();
|
|
||||||
|
|
||||||
// Avance le temps
|
|
||||||
audioForward.currentTime += delta * speedFactor;
|
|
||||||
|
|
||||||
// Clamp currentTime
|
|
||||||
if (audioForward.currentTime > audioForward.duration) {
|
|
||||||
audioForward.currentTime = audioForward.duration;
|
|
||||||
stopAudio();
|
|
||||||
}
|
|
||||||
updateProgress(audioForward.currentTime, audioForward.duration);
|
|
||||||
|
|
||||||
} else if (delta < 0) {
|
|
||||||
// Lecture reverse
|
|
||||||
if (currentDirection !== -1) {
|
|
||||||
// Switch direction: garder la position
|
|
||||||
audioReverse.currentTime = audioForward.duration - audioForward.currentTime;
|
|
||||||
audioForward.pause();
|
|
||||||
currentDirection = -1;
|
|
||||||
}
|
|
||||||
if (audioReverse.paused) audioReverse.play();
|
|
||||||
audioReverse.playbackRate = playbackRate;
|
|
||||||
audioForward.pause();
|
|
||||||
|
|
||||||
// Recul temps (en tenant compte que currentTime augmente dans les deux)
|
|
||||||
audioReverse.currentTime += -delta * speedFactor;
|
|
||||||
|
|
||||||
// Clamp currentTime
|
|
||||||
if (audioReverse.currentTime > audioReverse.duration) {
|
|
||||||
audioReverse.currentTime = audioReverse.duration;
|
|
||||||
stopAudio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mise à jour progress en miroir
|
const isReverse = speed < 0;
|
||||||
const forwardTime = audioReverse.duration - audioReverse.currentTime;
|
|
||||||
updateProgress(forwardTime, audioReverse.duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Animation vinyle
|
// Simuler reverse
|
||||||
if (!isPlaying) {
|
if (isReverse) {
|
||||||
vinyl.style.animationPlayState = 'running';
|
simulateReverse(Math.abs(speed));
|
||||||
isPlaying = true;
|
} else {
|
||||||
|
stopReverse();
|
||||||
|
let playbackSpeed = 1 + speed * 0.0003;
|
||||||
|
playbackSpeed = Math.max(0.5, Math.min(1.5, playbackSpeed));
|
||||||
|
controlPlayback(playbackSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPosition = position;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestion boutons +10s, -10s
|
function updateProgress() {
|
||||||
btnForward.addEventListener('click', () => {
|
const progressPercent = (audio.currentTime / audio.duration) * 100;
|
||||||
if (currentDirection === 1) {
|
progress.value = progressPercent;
|
||||||
audioForward.currentTime = Math.min(audioForward.duration, audioForward.currentTime + 10);
|
currentTimeEl.textContent = formatTime(audio.currentTime);
|
||||||
updateProgress(audioForward.currentTime, audioForward.duration);
|
}
|
||||||
syncReversePosition();
|
|
||||||
|
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 {
|
} else {
|
||||||
audioReverse.currentTime = Math.min(audioReverse.duration, audioReverse.currentTime + 10);
|
vinyl.style.animationPlayState = 'paused';
|
||||||
updateProgress(audioReverse.duration - audioReverse.currentTime, audioReverse.duration);
|
isPlaying = false;
|
||||||
syncForwardPosition();
|
|
||||||
}
|
}
|
||||||
if (!isPlaying) {
|
});
|
||||||
if (currentDirection === 1) audioForward.play();
|
|
||||||
else audioReverse.play();
|
|
||||||
vinyl.style.animationPlayState = 'running';
|
|
||||||
isPlaying = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
btnBackward.addEventListener('click', () => {
|
|
||||||
if (currentDirection === 1) {
|
|
||||||
audioForward.currentTime = Math.max(0, audioForward.currentTime - 10);
|
|
||||||
updateProgress(audioForward.currentTime, audioForward.duration);
|
|
||||||
syncReversePosition();
|
|
||||||
} else {
|
|
||||||
audioReverse.currentTime = Math.max(0, audioReverse.currentTime - 10);
|
|
||||||
updateProgress(audioReverse.duration - audioReverse.currentTime, audioReverse.duration);
|
|
||||||
syncForwardPosition();
|
|
||||||
}
|
|
||||||
if (!isPlaying) {
|
|
||||||
if (currentDirection === 1) audioForward.play();
|
|
||||||
else audioReverse.play();
|
|
||||||
vinyl.style.animationPlayState = 'running';
|
|
||||||
isPlaying = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Toggle loop
|
|
||||||
btnLoop.addEventListener('click', () => {
|
|
||||||
const newLoop = !audioForward.loop;
|
|
||||||
audioForward.loop = newLoop;
|
|
||||||
audioReverse.loop = newLoop;
|
|
||||||
btnLoop.textContent = newLoop ? 'LOOP ON' : 'LOOP';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Exemple : simulateur de position venant de l'encodeur (juste pour test)
|
|
||||||
// Remplace cette fonction par ta vraie récupération de la position de l'encodeur
|
|
||||||
let testPosition = 0;
|
|
||||||
setInterval(() => {
|
|
||||||
// Simule un mouvement avec des valeurs entre -20 et 20
|
|
||||||
// Ici, rien ne bouge (position stable) pour test arrêt
|
|
||||||
handlePosition(testPosition);
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Tu peux appeler handlePosition(positionEncoder) quand tu as la position réelle
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user