diff --git a/dlibrary/static/viewer.css b/dlibrary/static/viewer.css index c78f3ab..25e82b1 100644 --- a/dlibrary/static/viewer.css +++ b/dlibrary/static/viewer.css @@ -8,6 +8,8 @@ html, body { #controls { opacity: 0.8; animation: 2s linear forwards fade; + position: relative; + z-index: 300; } @keyframes fade { @@ -62,20 +64,28 @@ html, body { bottom: 0px; } -#viewer-images { - display: none; -} - -#image-container { +.image-container img { + position: fixed; + left: 0; + top: 0; height: 100vh; width: 100vw; - background-size: contain; - background-repeat: no-repeat; - background-position: center; + object-fit: contain; + object-position: 50% 50%; + background-color: #111; +} + +#current-image img { + z-index: 100; +} + +#preload-images img { + z-index: 0; } #page-num, #duration { position: fixed; + z-index: 200; font-size: 14pt; top: 10px; font-weight: bold; diff --git a/dlibrary/static/viewer.js b/dlibrary/static/viewer.js index 1f8fc81..f6229d2 100644 --- a/dlibrary/static/viewer.js +++ b/dlibrary/static/viewer.js @@ -1,7 +1,11 @@ const PROGRESS_UPDATE_INTERVAL = 50; +const PRELOAD_BACKWARD = 2; +const PRELOAD_FORWARD = 8; document.addEventListener('DOMContentLoaded', () => { - const pages = Array.from(document.querySelectorAll('img.viewer-image')); + 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 paused = true; @@ -42,26 +46,44 @@ document.addEventListener('DOMContentLoaded', () => { 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; - const previous = pages[currentPage]; - const current = pages[pageNum]; + const previous = IMAGES[currentPage]; + const current = IMAGES[pageNum]; if (current == null) { return; } - previous.classList.remove('current'); - current.classList.add('current'); - currentPage = pageNum; localStorage.setItem(`${WORK_ID}-currentPage`, currentPage); - const display = document.getElementById('image-container'); - display.style.backgroundImage = `url("${current.src}")`; + currentImage.replaceChildren(imageSrc(current)); document.getElementById('current-page').innerText = (pageNum + 1).toLocaleString(); + + setTimeout(preload, 1); } const durationDisplay = document.getElementById('duration'); @@ -102,7 +124,7 @@ document.addEventListener('DOMContentLoaded', () => { function exitToWork() { changeDuration(duration, true); - if (currentPage === pages.length - 1) { + if (currentPage === IMAGES.length - 1) { localStorage.removeItem(`${WORK_ID}-currentPage`); } window.location.href = `../${INDEX}`; diff --git a/dlibrary/templates/viewer.html b/dlibrary/templates/viewer.html index a2d61fd..aee53e8 100644 --- a/dlibrary/templates/viewer.html +++ b/dlibrary/templates/viewer.html @@ -5,15 +5,15 @@ {% endblock %} {% block body %} -