664 lines
20 KiB
JavaScript
664 lines
20 KiB
JavaScript
document.addEventListener('DOMContentLoaded', async () => {
|
|
const rutinaId = new URLSearchParams(window.location.search).get('routineId');
|
|
if (!rutinaId) return alert('No se proporcionó ID de rutina.');
|
|
|
|
const select = document.getElementById('selectAtleta');
|
|
const tituloRutina = document.getElementById('tituloRutina');
|
|
const tipoRutina = document.getElementById('tipoRutina');
|
|
const modalidadRutina = document.getElementById('modalidadRutina');
|
|
const inputFigura = document.getElementById('figura');
|
|
const btnEditarFormacion = document.getElementById('btnEditarFormacion');
|
|
const btnGuardarFormacion = document.getElementById('btnGuardarFormacion');
|
|
|
|
let editIndex = null;
|
|
let indexSeleccionado = null;
|
|
let modoDireccion = false;
|
|
let indexAtletaDireccion = null;
|
|
|
|
const rutina = await fetch(`/api/rutinas/${rutinaId}`).then(res => res.json());
|
|
const modalidad = rutina.modalidad;
|
|
|
|
const audioPlayer = document.getElementById('audioPlayer');
|
|
|
|
if (rutina.musicUrl) {
|
|
audioPlayer.src = rutina.musicUrl;
|
|
}
|
|
|
|
|
|
tituloRutina.textContent = rutina.title || rutina.nombreCompetencia;
|
|
tipoRutina.textContent = rutina.tipoCompetencia;
|
|
modalidadRutina.textContent = modalidad;
|
|
|
|
const atletas = await fetch('/api/users/athletes').then(res => res.json());
|
|
atletas.forEach(a => {
|
|
const opt = document.createElement('option');
|
|
opt.value = a._id;
|
|
opt.textContent = a.name;
|
|
select.appendChild(opt);
|
|
});
|
|
|
|
let figurasFINA = [];
|
|
try {
|
|
const res = await fetch('/catalog/figurasFINA.json');
|
|
figurasFINA = await res.json();
|
|
|
|
const sugerenciasBox = document.getElementById('sugerenciasFigura');
|
|
|
|
inputFigura.addEventListener('input', () => {
|
|
const val = inputFigura.value.trim().toLowerCase();
|
|
sugerenciasBox.innerHTML = '';
|
|
if (val.length < 1) return;
|
|
|
|
const matches = figurasFINA.filter(f => f.nombre.toLowerCase().includes(val));
|
|
matches.forEach(figura => {
|
|
const item = document.createElement('button');
|
|
item.type = 'button';
|
|
item.textContent = figura.nombre;
|
|
item.onclick = () => {
|
|
inputFigura.value = figura.nombre;
|
|
inputFigura.title = `${figura.descripcion} (${figura.categoria})`;
|
|
sugerenciasBox.innerHTML = '';
|
|
mostrarPreview(figura);
|
|
};
|
|
sugerenciasBox.appendChild(item);
|
|
});
|
|
});
|
|
|
|
inputFigura.addEventListener('blur', () => {
|
|
setTimeout(() => sugerenciasBox.innerHTML = '', 200);
|
|
});
|
|
|
|
function mostrarPreview(figura) {
|
|
document.getElementById('previewFigura').innerHTML = `
|
|
<img src="catalog/figuras/${figura.imagen}" alt="${figura.nombre}" class="img-fluid rounded border" style="max-height:150px;" />
|
|
<p class="mt-2">${figura.descripcion} <span class="badge bg-info">${figura.categoria}</span></p>
|
|
`;
|
|
}
|
|
} catch (err) {
|
|
console.warn('❌ No se pudo cargar el catálogo FINA:', err);
|
|
}
|
|
const tipoPiscinaSelect = document.getElementById('tipoPiscina');
|
|
|
|
const medidasPiscina = {
|
|
olimpica: { width: 1000, height: 500 },
|
|
semiolimpica: { width: 750, height: 375 },
|
|
fosa: { width: 600, height: 600 }
|
|
};
|
|
|
|
const tipoSeleccionado = rutina.tipoPiscina || 'olimpica';
|
|
tipoPiscinaSelect.value = tipoSeleccionado;
|
|
|
|
const piscinaWidth = medidasPiscina[tipoSeleccionado].width;
|
|
const piscinaHeight = medidasPiscina[tipoSeleccionado].height;
|
|
|
|
// Escalas de conversión a metros
|
|
const escalaX = 25 / piscinaWidth;
|
|
const escalaY = 20 / piscinaHeight;
|
|
|
|
function convertirAMetros(pxX, pxY) {
|
|
return {
|
|
metrosX: (pxX * escalaX).toFixed(2),
|
|
metrosY: (pxY * escalaY).toFixed(2)
|
|
};
|
|
}
|
|
|
|
const stage = new Konva.Stage({
|
|
container: 'piscina',
|
|
width: piscinaWidth,
|
|
height: piscinaHeight
|
|
});
|
|
const layer = new Konva.Layer();
|
|
stage.add(layer);
|
|
|
|
const divPiscina = document.getElementById('piscina');
|
|
divPiscina.style.width = `${piscinaWidth}px`;
|
|
divPiscina.style.height = `${piscinaHeight}px`;
|
|
document.getElementById('piscinaContainer').style.width = `${piscinaWidth + 20}px`;
|
|
|
|
dibujarCuadricula(layer, piscinaWidth, piscinaHeight);
|
|
|
|
function dibujarCuadricula(layer, ancho, alto, tamano = 45) {
|
|
for (let x = 0; x <= ancho; x += tamano) {
|
|
layer.add(new Konva.Line({
|
|
points: [x, 0, x, alto],
|
|
stroke: '#cceeff',
|
|
strokeWidth: 1
|
|
}));
|
|
}
|
|
for (let y = 0; y <= alto; y += tamano) {
|
|
layer.add(new Konva.Line({
|
|
points: [0, y, ancho, y],
|
|
stroke: '#cceeff',
|
|
strokeWidth: 1
|
|
}));
|
|
}
|
|
}
|
|
|
|
let formacionActual = [];
|
|
let atletasKonva = {};
|
|
let currentAtleta = null;
|
|
const maxAtletas = modalidad === 'solo' ? 1 : modalidad === 'duo' ? 2 : 8;
|
|
|
|
document.getElementById('btnAgregarAtleta').addEventListener('click', () => {
|
|
if (formacionActual.length >= maxAtletas) {
|
|
alert(`Modalidad "${modalidad}" permite un máximo de ${maxAtletas} atletas.`);
|
|
return;
|
|
}
|
|
|
|
const idAtleta = select.value;
|
|
const rol = document.getElementById('rolAtleta').value.trim().toLowerCase();
|
|
const idPersonalizado = document.getElementById('idPersonalizado').value.trim();
|
|
const figura = inputFigura?.value.trim();
|
|
const tipoElemento = document.getElementById('tipoElemento').value;
|
|
const codigoElemento = document.getElementById('codigoElemento').value.trim();
|
|
|
|
if (!idAtleta || !rol || !idPersonalizado) {
|
|
alert('Faltan datos del atleta');
|
|
return;
|
|
}
|
|
|
|
currentAtleta = {
|
|
atletaId: idAtleta,
|
|
rol,
|
|
idPersonalizado,
|
|
figura,
|
|
tipoElemento,
|
|
codigoElemento
|
|
};
|
|
alert('Haz clic en la piscina para colocarlo');
|
|
});
|
|
|
|
stage.on('click', () => {
|
|
if (!currentAtleta || modoDireccion) return;
|
|
|
|
const pos = stage.getPointerPosition();
|
|
const metros = convertirAMetros(pos.x, pos.y);
|
|
console.log(`📏 Posición en metros: (${metros.metrosX}m, ${metros.metrosY}m)`);
|
|
const atletaObj = { ...currentAtleta, x: pos.x, y: pos.y, grupo: '', direccion: null };
|
|
formacionActual.push(atletaObj);
|
|
dibujarAtleta(atletaObj);
|
|
currentAtleta = null;
|
|
|
|
document.getElementById('rolAtleta').value = '';
|
|
document.getElementById('idPersonalizado').value = '';
|
|
inputFigura.value = '';
|
|
inputFigura.title = '';
|
|
document.getElementById('previewFigura').innerHTML = '';
|
|
});
|
|
|
|
|
|
function dibujarAtleta(atleta) {
|
|
const color = atleta.rol === 'volador' ? 'purple' : atleta.rol === 'pilar' ? 'blue' : 'red';
|
|
|
|
const metros = convertirAMetros(atleta.x, atleta.y);
|
|
|
|
const circle = new Konva.Circle({
|
|
x: atleta.x,
|
|
y: atleta.y,
|
|
radius: 15,
|
|
fill: color,
|
|
stroke: 'white',
|
|
strokeWidth: 2,
|
|
draggable: !modoDireccion
|
|
});
|
|
|
|
const text = new Konva.Text({
|
|
x: atleta.x - 10,
|
|
y: atleta.y - 7,
|
|
text: atleta.idPersonalizado,
|
|
fontSize: 12,
|
|
fill: 'white'
|
|
});
|
|
|
|
const figuraText = new Konva.Text({
|
|
x: atleta.x - 25,
|
|
y: atleta.y + 18,
|
|
text: atleta.figura || '',
|
|
fontSize: 10,
|
|
fill: '#333',
|
|
fontStyle: 'italic'
|
|
});
|
|
figuraText.listening(false);
|
|
|
|
const coordText = new Konva.Text({
|
|
x: atleta.x - 35,
|
|
y: atleta.y + 30,
|
|
text: `${metros.metrosX}m, ${metros.metrosY}m`,
|
|
fontSize: 9,
|
|
fill: '#666'
|
|
});
|
|
coordText.listening(false);
|
|
|
|
circle.on('dblclick', () => {
|
|
const i = formacionActual.findIndex(a => a.idPersonalizado === atleta.idPersonalizado);
|
|
const html = `
|
|
<div class="p-2" style="min-width:200px;">
|
|
<h6 class="mb-1">${atleta.figura || 'Sin figura'}</h6>
|
|
<button class="btn btn-sm btn-outline-primary w-100 mb-2" onclick="activarModoDireccion(${i})">➤ Añadir Dirección</button>
|
|
<button class="btn btn-sm btn-outline-secondary w-100" onclick="alert('Función editar aún no implementada')">✏ Editar/Eliminar</button>
|
|
</div>
|
|
`;
|
|
showPopover(circle.x(), circle.y(), html);
|
|
});
|
|
|
|
circle.on('dragend', () => {
|
|
const newX = circle.x();
|
|
const newY = circle.y();
|
|
const i = formacionActual.findIndex(a => a.idPersonalizado === atleta.idPersonalizado);
|
|
if (i !== -1) {
|
|
formacionActual[i].x = newX;
|
|
formacionActual[i].y = newY;
|
|
}
|
|
|
|
const nuevosMetros = convertirAMetros(newX, newY);
|
|
coordText.text(`${nuevosMetros.metrosX}m, ${nuevosMetros.metrosY}m`);
|
|
coordText.x(newX - 35);
|
|
coordText.y(newY + 30);
|
|
|
|
text.x(newX - 10);
|
|
text.y(newY - 7);
|
|
|
|
figuraText.x(newX - 25);
|
|
figuraText.y(newY + 18);
|
|
|
|
layer.batchDraw();
|
|
});
|
|
|
|
layer.add(circle);
|
|
atletasKonva[atleta.idPersonalizado] = {
|
|
circle,
|
|
text,
|
|
figuraText,
|
|
coordText
|
|
};
|
|
layer.add(text);
|
|
layer.add(figuraText);
|
|
layer.add(coordText);
|
|
|
|
if (atleta.direccion) {
|
|
const dir = new Konva.Line({
|
|
points: [atleta.direccion.x1, atleta.direccion.y1, atleta.direccion.x2, atleta.direccion.y2],
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
dash: [4, 4]
|
|
});
|
|
layer.add(dir);
|
|
}
|
|
|
|
layer.draw();
|
|
}
|
|
|
|
|
|
window.activarModoDireccion = function(index) {
|
|
modoDireccion = true;
|
|
indexAtletaDireccion = index;
|
|
document.getElementById('popoverAtleta')?.remove();
|
|
alert('Haz clic para trazar dirección.');
|
|
}
|
|
|
|
stage.on('mousedown', () => {
|
|
if (!modoDireccion || indexAtletaDireccion === null) return;
|
|
|
|
const start = stage.getPointerPosition();
|
|
const atleta = formacionActual[indexAtletaDireccion];
|
|
const linea = new Konva.Line({
|
|
points: [start.x, start.y, start.x, start.y],
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
dash: [4, 4]
|
|
});
|
|
layer.add(linea);
|
|
|
|
stage.on('mousemove.direccion', () => {
|
|
const pos = stage.getPointerPosition();
|
|
linea.points([start.x, start.y, pos.x, pos.y]);
|
|
layer.batchDraw();
|
|
});
|
|
|
|
stage.on('mouseup.direccion', () => {
|
|
const end = stage.getPointerPosition();
|
|
atleta.direccion = {
|
|
x1: start.x,
|
|
y1: start.y,
|
|
x2: end.x,
|
|
y2: end.y
|
|
};
|
|
modoDireccion = false;
|
|
indexAtletaDireccion = null;
|
|
stage.off('mousemove.direccion');
|
|
stage.off('mouseup.direccion');
|
|
});
|
|
});
|
|
|
|
function showPopover(x, y, contentHTML) {
|
|
document.getElementById('popoverAtleta')?.remove();
|
|
|
|
const popover = document.createElement('div');
|
|
popover.id = 'popoverAtleta';
|
|
popover.innerHTML = contentHTML;
|
|
popover.style.position = 'absolute';
|
|
popover.style.left = `${x + 50}px`;
|
|
popover.style.top = `${y + 100}px`;
|
|
popover.style.zIndex = '1000';
|
|
popover.style.background = '#fff';
|
|
popover.style.border = '1px solid #ccc';
|
|
popover.style.boxShadow = '0 2px 8px rgba(0,0,0,0.2)';
|
|
popover.style.padding = '10px';
|
|
popover.style.borderRadius = '6px';
|
|
|
|
document.body.appendChild(popover);
|
|
|
|
setTimeout(() => {
|
|
document.addEventListener('click', function handler(e) {
|
|
if (!popover.contains(e.target)) {
|
|
popover.remove();
|
|
document.removeEventListener('click', handler);
|
|
}
|
|
});
|
|
}, 100);
|
|
}
|
|
|
|
function animarTransicion(nuevaFormacion) {
|
|
nuevaFormacion.forEach(a => {
|
|
const obj = atletasKonva[a.idPersonalizado];
|
|
if (obj) {
|
|
const { circle, text, figuraText, coordText } = obj;
|
|
|
|
// Animar círculo
|
|
new Konva.Tween({
|
|
node: circle,
|
|
duration: 1.0,
|
|
x: a.x,
|
|
y: a.y,
|
|
easing: Konva.Easings.EaseInOut,
|
|
}).play();
|
|
|
|
// Mover textos en paralelo
|
|
new Konva.Tween({
|
|
node: text,
|
|
duration: 1.0,
|
|
x: a.x - 10,
|
|
y: a.y - 7,
|
|
easing: Konva.Easings.EaseInOut,
|
|
}).play();
|
|
|
|
new Konva.Tween({
|
|
node: figuraText,
|
|
duration: 1.0,
|
|
x: a.x - 25,
|
|
y: a.y + 18,
|
|
easing: Konva.Easings.EaseInOut,
|
|
}).play();
|
|
|
|
new Konva.Tween({
|
|
node: coordText,
|
|
duration: 1.0,
|
|
x: a.x - 35,
|
|
y: a.y + 30,
|
|
easing: Konva.Easings.EaseInOut,
|
|
onUpdate: () => {
|
|
const metros = convertirAMetros(a.x, a.y);
|
|
coordText.text(`${metros.metrosX}m, ${metros.metrosY}m`);
|
|
}
|
|
}).play();
|
|
|
|
} else {
|
|
dibujarAtleta(a);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
btnGuardarFormacion.addEventListener('click', async () => {
|
|
const nombre = document.getElementById('nombreFormacion').value.trim();
|
|
const notas = document.getElementById('notasFormacion').value.trim();
|
|
const duracion = parseInt(document.getElementById('duracionFormacion').value);
|
|
|
|
if (!nombre || formacionActual.length === 0) {
|
|
alert('Agrega nombre de formación y al menos un atleta');
|
|
return;
|
|
}
|
|
|
|
const body = {
|
|
nombreColoquial: nombre,
|
|
notasTacticas: notas,
|
|
duracion: duracion || 0,
|
|
atletas: formacionActual.map(a => ({
|
|
atletaId: a.atletaId._id || a.atletaId,
|
|
idPersonalizado: a.idPersonalizado,
|
|
x: a.x,
|
|
y: a.y,
|
|
rol: a.rol,
|
|
grupo: a.grupo,
|
|
direccion: a.direccion,
|
|
figura: a.figura,
|
|
tipoElemento: a.tipoElemento,
|
|
codigoElemento: a.codigoElemento,
|
|
tipoPiscina: tipoPiscinaSelect.value,
|
|
|
|
|
|
}))
|
|
};
|
|
|
|
const method = editIndex === null ? 'POST' : 'PUT';
|
|
const endpoint = editIndex === null
|
|
? `/api/rutinas/${rutinaId}/formations`
|
|
: `/api/rutinas/${rutinaId}/formations/${editIndex}`;
|
|
|
|
const res = await fetch(endpoint, {
|
|
method,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(body)
|
|
});
|
|
|
|
if (res.ok) {
|
|
alert(editIndex === null ? '✅ Formación guardada' : '✏️ Formación actualizada');
|
|
window.location.reload();
|
|
} else {
|
|
alert('❌ Error al guardar formación');
|
|
}
|
|
});
|
|
|
|
const timeline = document.getElementById('lineaTiempo');
|
|
new Sortable(timeline, {
|
|
animation: 150,
|
|
onEnd: async (evt) => {
|
|
const nuevaLista = [...timeline.children].map(btn => parseInt(btn.dataset.index));
|
|
const nuevasFormaciones = nuevaLista.map(i => formaciones[i]);
|
|
|
|
try {
|
|
const res = await fetch(`/api/rutinas/${rutinaId}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ formaciones: nuevasFormaciones })
|
|
});
|
|
|
|
const json = await res.json();
|
|
if (res.ok) {
|
|
console.log('✅ Formaciones reordenadas');
|
|
} else {
|
|
console.warn('⚠️ Error al guardar nuevo orden:', json);
|
|
}
|
|
} catch (err) {
|
|
console.error('❌ Error de red al reordenar:', err);
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
const formaciones = await fetch(`/api/rutinas/${rutinaId}/formations`).then(res => res.json());
|
|
|
|
if (Array.isArray(formaciones)) {
|
|
formaciones.forEach((f, i) => {
|
|
const block = document.createElement('button');
|
|
block.className = 'btn btn-outline-secondary btn-sm me-2 step';
|
|
block.textContent = `${f.nombreColoquial || `Formación ${i + 1}`} (${f.duracion || '?'}s)`;
|
|
block.dataset.index = i;
|
|
block.title = f.notasTacticas || '';
|
|
timeline.appendChild(block);
|
|
});
|
|
}
|
|
|
|
timeline.addEventListener('click', (e) => {
|
|
if (!e.target.classList.contains('step')) return;
|
|
|
|
indexSeleccionado = parseInt(e.target.dataset.index);
|
|
const seleccionada = formaciones[indexSeleccionado];
|
|
if (!seleccionada) return;
|
|
|
|
document.getElementById('nombreFormacion').value = seleccionada.nombreColoquial || '';
|
|
document.getElementById('notasFormacion').value = seleccionada.notasTacticas || '';
|
|
|
|
formacionActual = seleccionada.atletas.map(a => ({ ...a }));
|
|
|
|
const nuevaFormacion = seleccionada.atletas.map(a => ({ ...a }));
|
|
animarTransicion(nuevaFormacion);
|
|
formacionActual = nuevaFormacion;
|
|
|
|
|
|
btnEditarFormacion.disabled = false;
|
|
btnEditarFormacion.className = 'btn btn-outline-secondary btn-sm';
|
|
btnEditarFormacion.innerHTML = '✏ Editar formación';
|
|
|
|
btnGuardarFormacion.textContent = '💾 Guardar Formación';
|
|
btnGuardarFormacion.classList.remove('btn-warning');
|
|
btnGuardarFormacion.classList.add('btn-primary');
|
|
|
|
editIndex = null;
|
|
});
|
|
|
|
const syncPuntos = [];
|
|
let tiempoAcumulado = 0;
|
|
|
|
formaciones.forEach((f, i) => {
|
|
syncPuntos.push({
|
|
index: i,
|
|
inicio: tiempoAcumulado,
|
|
fin: tiempoAcumulado + (f.duracion || 0)
|
|
});
|
|
tiempoAcumulado += (f.duracion || 0);
|
|
});
|
|
|
|
|
|
btnEditarFormacion.addEventListener('click', () => {
|
|
if (indexSeleccionado !== null) {
|
|
editIndex = indexSeleccionado;
|
|
const a = formacionActual[0] || {};
|
|
document.getElementById('rolAtleta').value = a.rol || '';
|
|
document.getElementById('idPersonalizado').value = a.idPersonalizado || '';
|
|
inputFigura.value = a.figura || '';
|
|
inputFigura.title = '';
|
|
|
|
btnEditarFormacion.className = 'btn btn-warning btn-sm d-inline-flex align-items-center gap-2';
|
|
btnEditarFormacion.innerHTML = '🟡 En edición activa';
|
|
|
|
btnGuardarFormacion.textContent = 'Actualizar Formación';
|
|
btnGuardarFormacion.classList.remove('btn-primary');
|
|
btnGuardarFormacion.classList.add('btn-warning');
|
|
} else {
|
|
alert('Selecciona una formación desde la línea de tiempo primero.');
|
|
}
|
|
});
|
|
|
|
|
|
|
|
try {
|
|
const res = await fetch(`/api/rutinas/${rutinaId}/piscina`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ width: newWidth, height: newHeight })
|
|
});
|
|
|
|
if (!res.ok) throw new Error('No se pudo guardar en la base de datos');
|
|
|
|
stage.width(newWidth);
|
|
stage.height(newHeight);
|
|
divPiscina.style.width = `${newWidth}px`;
|
|
divPiscina.style.height = `${newHeight}px`;
|
|
document.getElementById('piscinaContainer').style.width = `${newWidth + 20}px`;
|
|
|
|
layer.destroyChildren();
|
|
dibujarCuadricula(layer, newWidth, newHeight);
|
|
formacionActual.forEach(a => dibujarAtleta(a));
|
|
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Piscina actualizada',
|
|
text: 'El tamaño y la cuadrícula fueron actualizados correctamente.'
|
|
});
|
|
} catch (err) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error',
|
|
text: 'No se pudo actualizar la piscina en la base de datos.'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Observador de redimensionamiento para mantener la tarjeta ajustada
|
|
const piscinaCard = document.querySelector('#piscinaContainer').closest('.card');
|
|
const resizeObserver = new ResizeObserver(() => {
|
|
if (piscinaCard) {
|
|
piscinaCard.style.height = 'auto';
|
|
}
|
|
});
|
|
resizeObserver.observe(document.getElementById('piscina'));
|
|
|
|
// Crear WaveSurfer
|
|
const wave = WaveSurfer.create({
|
|
container: '#waveform',
|
|
waveColor: '#A8DBA8',
|
|
progressColor: '#3B8686',
|
|
height: 100,
|
|
responsive: true
|
|
});
|
|
|
|
if (rutina.musicUrl) {
|
|
wave.load(rutina.musicUrl);
|
|
}
|
|
|
|
const playPauseBtn = document.getElementById('playPauseBtn');
|
|
|
|
playPauseBtn.addEventListener('click', () => {
|
|
wave.playPause();
|
|
});
|
|
|
|
wave.on('play', () => {
|
|
playPauseBtn.textContent = '⏸︎ Pausar';
|
|
});
|
|
|
|
wave.on('pause', () => {
|
|
playPauseBtn.textContent = '▶ Reproducir';
|
|
});
|
|
|
|
wave.on('finish', () => {
|
|
playPauseBtn.textContent = '▶ Reproducir';
|
|
});
|
|
|
|
wave.on('audioprocess', (currentTime) => {
|
|
syncPuntos.forEach(punto => {
|
|
const btn = document.querySelector(`.step[data-index="${punto.index}"]`);
|
|
if (!btn) return;
|
|
|
|
if (currentTime >= punto.inicio && currentTime < punto.fin) {
|
|
btn.classList.add('active');
|
|
|
|
if (indexSeleccionado !== punto.index) {
|
|
indexSeleccionado = punto.index;
|
|
const seleccionada = formaciones[punto.index];
|
|
if (seleccionada) {
|
|
formacionActual = seleccionada.atletas.map(a => ({ ...a }));
|
|
const nuevaFormacion = seleccionada.atletas.map(a => ({ ...a }));
|
|
animarTransicion(nuevaFormacion);
|
|
formacionActual = nuevaFormacion;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
btn.classList.remove('active');
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|