const PRELOAD_BACKWARD = 2; const PRELOAD_FORWARD = 8; document.addEventListener('DOMContentLoaded', () => { const currentImage = document.getElementById('current-image'); const preloadImages = document.getElementById('preload-images'); let currentPage = parseInt(localStorage.getItem(`${WORK_ID}-currentPage`)) || 0; let duration = parseInt(localStorage.getItem(`${WORK_ID}-duration`)) || 10; let rtl = (localStorage.getItem(`${WORK_ID}-rtl`) !== "false"); let paused = true; let elapsed = 0; let timerLastRun = null; let timerAnimationRequestID = null; function requestTimer() { timerAnimationRequestID = window.requestAnimationFrame(runTimer); } function runTimer(now) { if (paused) { return; } if (timerLastRun === null) { elapsed = 0; } else { elapsed += now - timerLastRun; } timerLastRun = now; if (elapsed >= duration*1000) { changePage(currentPage + 1); elapsed = 0; } updateBar(); requestTimer(); } const progressBar = document.getElementById('progress'); function updateBar() { progressBar.style.width = `${100*elapsed/(1000*duration)}%`; } function stopTimer() { if (timerAnimationRequestID) { window.cancelAnimationFrame(timerAnimationRequestID); timerAnimationRequestID = null; } timerLastRun = null; elapsed = 0; updateBar(); } function imageSrc(s) { const img = new Image(); img.src = s; return img; } function preload() { if (!currentImage.getElementsByTagName('img')[0].complete) { setTimeout(preload, 50); return; } preloadImages.replaceChildren(...( IMAGES.slice( Math.max(currentPage - PRELOAD_BACKWARD, 0), currentPage + PRELOAD_FORWARD + 1, ).map(imageSrc) )); } function changePage(pageNum) { elapsed = 0; updateBar(); const previous = IMAGES[currentPage]; const current = IMAGES[pageNum]; if (current == null) { return; } currentPage = pageNum; localStorage.setItem(`${WORK_ID}-currentPage`, currentPage); currentImage.replaceChildren(imageSrc(current)); document.getElementById('current-page').innerText = (pageNum + 1).toLocaleString(); setTimeout(preload, 1); } const durationDisplay = document.getElementById('duration'); function changeDuration(secs, pause) { duration = secs; localStorage.setItem(`${WORK_ID}-duration`, duration); paused = pause; durationDisplay.textContent = duration.toLocaleString() + 's'; if (paused) { durationDisplay.style.textDecoration = "line-through 2px"; stopTimer(); } else { durationDisplay.style.textDecoration = ""; requestTimer(); } } function left() { if (currentPage === 0) { rtl = true; localStorage.setItem(`${WORK_ID}-rtl`, rtl); } changePage(currentPage + (rtl ? 1 : -1)); } function right() { if (currentPage === 0) { rtl = false; localStorage.setItem(`${WORK_ID}-rtl`, rtl); } changePage(currentPage + (rtl ? -1 : 1)); } function restart() { changePage(0); } function exitToWork() { changeDuration(duration, true); if (currentPage === IMAGES.length - 1) { localStorage.removeItem(`${WORK_ID}-currentPage`); } window.location.href = `../${INDEX}`; } function hideTapZones() { document.getElementById('controls').style.opacity = 0; } changePage(currentPage); changeDuration(duration, paused); document.onkeydown = event => { hideTapZones(); switch (event.key) { case "ArrowLeft": event.preventDefault(); left(); break; case "ArrowRight": event.preventDefault(); right(); break; case " ": event.preventDefault(); changeDuration(duration, !paused); break; case "ArrowUp": event.preventDefault(); if (2 <= duration && duration <= 10) { changeDuration(duration - 1, false); } else if (10 < duration && duration <= 20) { changeDuration(duration - 2.5, false); } else if (20 < duration) { changeDuration(duration - 5, false); } break; case "ArrowDown": event.preventDefault(); if (duration < 10) { changeDuration(duration + 1, false); } else if (10 <= duration && duration < 20) { changeDuration(duration + 2.5, false); } else if (20 <= duration) { changeDuration(duration + 5, false); } break; case "Enter": event.preventDefault(); restart(); break; case "Escape": event.preventDefault(); exitToWork(); break; } }; document.onclick = hideTapZones; document.getElementById("tap-left").onclick = left; document.getElementById("tap-right").onclick = right; document.getElementById("tap-restart").onclick = restart; document.getElementById("tap-back").onclick = exitToWork; });