Improvements to Lazy Loading

- Now applied to all images over 150x150px

- Stores the width and height in the WeakMap rather than using
percentages for accuracy

- When oneboxed images are hidden, they are given a subtle border for better
visibility.

- Don't apply when in the composer. Causes flickering.
This commit is contained in:
Robin Ward 2018-12-21 11:29:29 -05:00
parent 7feabd9e49
commit 0e710dc573
2 changed files with 31 additions and 14 deletions

View File

@ -2,7 +2,10 @@ const OBSERVER_OPTIONS = {
rootMargin: "50%" // load images slightly before they're visible rootMargin: "50%" // load images slightly before they're visible
}; };
const imageSources = new WeakMap(); // Min size in pixels for consideration for lazy loading
const MINIMUM_SIZE = 150;
const hiddenData = new WeakMap();
const LOADING_DATA = const LOADING_DATA =
"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
@ -12,7 +15,12 @@ function hide(image) {
image.classList.add("d-lazyload"); image.classList.add("d-lazyload");
image.classList.add("d-lazyload-hidden"); image.classList.add("d-lazyload-hidden");
imageSources.set(image, { src: image.src, srcset: image.srcset }); hiddenData.set(image, {
src: image.src,
srcset: image.srcset,
width: image.width,
height: image.height
});
image.removeAttribute("srcset"); image.removeAttribute("srcset");
image.src = image.dataset.smallUpload || LOADING_DATA; image.src = image.dataset.smallUpload || LOADING_DATA;
@ -21,9 +29,9 @@ function hide(image) {
// Restore an image when onscreen // Restore an image when onscreen
function show(image) { function show(image) {
let sources = imageSources.get(image); let imageData = hiddenData.get(image);
if (sources) { if (imageData) {
const copyImg = new Image(); const copyImg = new Image();
copyImg.onload = () => { copyImg.onload = () => {
image.src = copyImg.src; image.src = copyImg.src;
@ -35,14 +43,14 @@ function show(image) {
copyImg.onload = null; copyImg.onload = null;
}; };
copyImg.src = sources.src; copyImg.src = imageData.src;
copyImg.srcset = sources.srcset || copyImg.srcset; copyImg.srcset = imageData.srcset || copyImg.srcset;
copyImg.style.position = "absolute"; copyImg.style.position = "absolute";
copyImg.style.top = 0; copyImg.style.top = 0;
copyImg.style.left = 0; copyImg.style.left = 0;
copyImg.style.height = "100%"; copyImg.style.width = imageData.width;
copyImg.style.width = "100%"; copyImg.style.height = imageData.height;
image.parentNode.appendChild(copyImg); image.parentNode.appendChild(copyImg);
} else { } else {
@ -62,10 +70,15 @@ export function setupLazyLoading(api) {
}); });
}, OBSERVER_OPTIONS); }, OBSERVER_OPTIONS);
api.decorateCooked($post => { api.decorateCooked(
$(".lightbox img", $post).each((_, img) => { $post => {
hide(img); $("img", $post).each((_, img) => {
observer.observe(img); if (img.width >= MINIMUM_SIZE && img.height >= MINIMUM_SIZE) {
}); hide(img);
}); observer.observe(img);
}
});
},
{ onlyStream: true }
);
} }

View File

@ -13,6 +13,10 @@
box-sizing: border-box; box-sizing: border-box;
} }
.onebox img.d-lazyload-hidden {
border: 1px solid $primary-low;
}
.cooked img.d-lazyload { .cooked img.d-lazyload {
transition: opacity 0.4s 0.75s ease; transition: opacity 0.4s 0.75s ease;
} }