mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-26 17:54:52 +02:00
improved lazy loading
This commit is contained in:
38
docs/js/site/better-lazy-loading.js
Normal file
38
docs/js/site/better-lazy-loading.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* This file takes any <img> with loading="lazy" and rewrites it
|
||||
* so that it starts to load much earlier than browsers would load
|
||||
* them, so that they're already done by the time the user gets to
|
||||
* them. This (mostly) prevents the whole "you can see the image
|
||||
* loading in", which is super shitty UX.
|
||||
*/
|
||||
|
||||
const images = Array.from(
|
||||
document.querySelectorAll(`img.LaTeX.SVG[loading=lazy]`)
|
||||
);
|
||||
|
||||
// Deactivate the images
|
||||
images.forEach((img) => {
|
||||
img.dataset.src = img.src;
|
||||
img.src = ``;
|
||||
img.removeAttribute(`loading`);
|
||||
});
|
||||
|
||||
// Then make their activation conditional on whether
|
||||
// they're close to being on-screen or not.
|
||||
let observer = new IntersectionObserver(
|
||||
function (entries) {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
const img = entry.target;
|
||||
img.src = img.dataset.src;
|
||||
const pos = images.indexOf(img);
|
||||
images.splice(pos, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ rootMargin: `100%` }
|
||||
);
|
||||
|
||||
images.forEach((image) => {
|
||||
observer.observe(image);
|
||||
});
|
@@ -1,17 +1,13 @@
|
||||
const comments = document.getElementById(`disqus_thread`);
|
||||
|
||||
document.addEventListener("scroll", scrollHandler, { passive: true });
|
||||
|
||||
function scrollHandler() {
|
||||
var bbox = comments.getBoundingClientRect();
|
||||
var top = bbox.top;
|
||||
var limit = window.innerHeight;
|
||||
if (top < limit) {
|
||||
loadDisqus();
|
||||
}
|
||||
}
|
||||
new IntersectionObserver(function (entries) {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
loadDisqus();
|
||||
}
|
||||
});
|
||||
}).observe(document.getElementById(`disqus_thread`));
|
||||
|
||||
let loadDisqus = () => {
|
||||
loadDisqus = () => {};
|
||||
console.log(`loading Disqus comments`);
|
||||
|
||||
globalThis.disqus_config = function () {
|
||||
@@ -24,9 +20,4 @@ let loadDisqus = () => {
|
||||
script.async = true;
|
||||
script.setAttribute("data-timestamp", Date.now());
|
||||
document.head.appendChild(script);
|
||||
|
||||
loadDisqus = () => {};
|
||||
document.removeEventListener("scroll", scrollHandler);
|
||||
};
|
||||
|
||||
scrollHandler();
|
||||
|
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* This file takes any <img> with loading="lazy" and rewrites it
|
||||
* so that it starts to load much earlier than browsers would load
|
||||
* them, so that they're already done by the time the user gets to
|
||||
* them. This prevents the ridiculous "don't start loading the img
|
||||
* until we're already looking at the empty bounding box".
|
||||
*/
|
||||
|
||||
const images = Array.from(
|
||||
document.querySelectorAll(`img.LaTeX.SVG[loading=lazy]`)
|
||||
);
|
||||
|
||||
// First, make images inert. As this happens before the document
|
||||
// becomes active, this prevents images from loading anything.
|
||||
//
|
||||
// Also, by having JS deactivate the images, anyone running with
|
||||
// JS disabled will still see images load in properly. In fact,
|
||||
// the "lazy" attribute gets ignored when JS is disabled and all
|
||||
// images will just load in immediately.
|
||||
|
||||
images.forEach((img) => {
|
||||
// non-negotiable order of operations:
|
||||
img.dataset.src = img.src;
|
||||
img.src = ``;
|
||||
img.removeAttribute(`loading`);
|
||||
});
|
||||
|
||||
// Then tack on the functionality that reactivates them based on viewport distance.
|
||||
|
||||
let lock = false;
|
||||
let retry = false;
|
||||
|
||||
/**
|
||||
* Test all images during scroll, in a way that doesn't hang the browser.
|
||||
*/
|
||||
function testImages() {
|
||||
if (lock) {
|
||||
if (retry) retry = clearTimeout(retry);
|
||||
retry = setTimeout(testImages, 200);
|
||||
}
|
||||
|
||||
lock = true;
|
||||
|
||||
let height = document.documentElement.clientHeight;
|
||||
|
||||
for (let pos = images.length - 1; pos >= 0; pos--) {
|
||||
test(images[pos], pos, height);
|
||||
}
|
||||
|
||||
if (images.length === 0) {
|
||||
window.removeEventListener("scroll", testImages);
|
||||
if (retry) clearTimeout(retry);
|
||||
}
|
||||
|
||||
lock = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test individual images for whether or not they should load.
|
||||
*/
|
||||
function test(img, pos, height) {
|
||||
let top = img.getBoundingClientRect().top;
|
||||
top = top < height;
|
||||
|
||||
let bottom = img.getBoundingClientRect().bottom;
|
||||
bottom = bottom > -height;
|
||||
|
||||
if (top || bottom) {
|
||||
img.src = img.dataset.src;
|
||||
images.splice(pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember to listen for scroll passively. If you don't, bad things happen.
|
||||
*/
|
||||
window.addEventListener("scroll", testImages, { passive: true });
|
Reference in New Issue
Block a user