smarter image preloading

This commit is contained in:
xenofem 2024-02-11 17:13:10 -05:00
parent 6bc8332f47
commit 89093ac490
3 changed files with 56 additions and 23 deletions

View file

@ -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;

View file

@ -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}`;

View file

@ -5,15 +5,15 @@
<script>
const WORK_ID = "{{ work['id'] }}";
const INDEX = "{{ index() }}";
const IMAGES = [
{% for filename in images %}
"{{ root() }}/images/{{ work['id'] }}/{{ filename }}",
{% endfor %}
];
</script>
<script src="{{ root() }}/static/viewer.js"></script>
{% endblock %}
{% block body %}
<div id="viewer-images">
{% for filename in images %}
<img src="{{ root() }}/images/{{ work['id'] }}/{{ filename }}" class="viewer-image">
{% endfor %}
</div>
<div id="progress"></div>
<div id="page-num">
<table>
@ -46,5 +46,6 @@
</svg>
</div>
</div>
<div id="image-container"></div>
<div class="image-container" id="current-image"></div>
<div class="image-container" id="preload-images"></div>
{% endblock %}