sites/flux.vision/flux/static/js/site.js

62 lines
2.1 KiB
JavaScript
Raw Normal View History

/* Tile loading, after the 2004-2019 site.
*
* The original showed animated static (void.gif, 79 frames at 40ms) in each
* tile until jquery.lazyload fetched the real image on scroll. On a 2014
* connection fetching 231 library images, that static was visible for a good
* while. Served locally it is gone in a few milliseconds and the effect is
* lost entirely, so the hold is made deliberate rather than left to latency:
* the noise runs for at least HOLD_MS whatever the connection does.
*
* Loading also starts only once a tile is genuinely near the viewport, and
* each tile takes a small stagger, so a screen of them resolves in a ripple
* rather than all snapping at once.
*/
(function () {
"use strict";
var HOLD_MS = 320; /* minimum time the static is on screen */
var STAGGER = 35; /* ms between neighbouring tiles resolving */
var MARGIN = "80px";
var tiles = document.querySelectorAll(".art-preview.lazy[data-src]");
if (!tiles.length) return;
var queued = 0, lastAt = 0;
function reveal(el, src) {
el.style.setProperty("--src", "url('" + src + "')");
el.classList.add("loaded");
}
function load(el) {
var src = el.getAttribute("data-src");
if (!src || el.dataset.done) return;
el.dataset.done = "1";
var now = Date.now();
var slot = Math.max(now, lastAt + STAGGER);
lastAt = slot;
var floor = slot - now + HOLD_MS; /* earliest this tile may resolve */
var began = now, ready = false, elapsed = 0;
var img = new Image();
img.onload = function () {
ready = true;
elapsed = Date.now() - began;
setTimeout(function () { reveal(el, src); }, Math.max(0, floor - elapsed));
};
img.onerror = function () { el.classList.add("empty"); };
img.src = src;
}
if (!("IntersectionObserver" in window)) {
Array.prototype.forEach.call(tiles, load);
return;
}
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) { load(e.target); io.unobserve(e.target); }
});
}, { rootMargin: MARGIN });
Array.prototype.forEach.call(tiles, function (t) { io.observe(t); });
})();