FEATURE: Lazily Load Images as they scroll into the viewport.
This feature uses the Intersection Observer API https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API It should be compatible with all modern browsers. Non-Edge IE is *NOT* supported, so in that particular browser images are loaded by default.
This commit is contained in:
parent
5358f25fc6
commit
6797a710aa
|
@ -1,5 +1,6 @@
|
|||
import highlightSyntax from "discourse/lib/highlight-syntax";
|
||||
import lightbox from "discourse/lib/lightbox";
|
||||
import { setupLazyLoading } from "discourse/lib/lazy-load-images";
|
||||
import { setTextDirections } from "discourse/lib/text-direction";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
|
||||
|
@ -14,6 +15,8 @@ export default {
|
|||
api.decorateCooked(setTextDirections);
|
||||
}
|
||||
|
||||
setupLazyLoading(api);
|
||||
|
||||
api.decorateCooked($elem => {
|
||||
const players = $("audio", $elem);
|
||||
if (players.length) {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
const OBSERVER_OPTIONS = {
|
||||
rootMargin: "50%" // load images slightly before they're visible
|
||||
};
|
||||
|
||||
// We hide an image by replacing it with a transparent gif
|
||||
function hide(image) {
|
||||
image.classList.add("d-lazyload");
|
||||
image.classList.add("d-lazyload-hidden");
|
||||
image.setAttribute("data-src", image.getAttribute("src"));
|
||||
image.setAttribute(
|
||||
"src",
|
||||
"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
|
||||
);
|
||||
}
|
||||
|
||||
// Restore an image from the `data-src` attribute
|
||||
function show(image) {
|
||||
let dataSrc = image.getAttribute("data-src");
|
||||
if (dataSrc) {
|
||||
image.setAttribute("src", dataSrc);
|
||||
image.classList.remove("d-lazyload-hidden");
|
||||
}
|
||||
}
|
||||
|
||||
export function setupLazyLoading(api) {
|
||||
// Old IE don't support this API
|
||||
if (!("IntersectionObserver" in window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
const { target } = entry;
|
||||
|
||||
if (entry.isIntersecting) {
|
||||
show(target);
|
||||
observer.unobserve(target);
|
||||
} else {
|
||||
// The Observer is triggered when entries are added. This allows
|
||||
// us to hide things that start off screen.
|
||||
hide(target);
|
||||
}
|
||||
});
|
||||
}, OBSERVER_OPTIONS);
|
||||
|
||||
api.decorateCooked($post => {
|
||||
$(".lightbox img", $post).each((_, $img) => observer.observe($img));
|
||||
});
|
||||
}
|
|
@ -6,6 +6,16 @@
|
|||
opacity: 0.9;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
background: rgba($primary, 0.25);
|
||||
}
|
||||
|
||||
.d-lazyload-hidden {
|
||||
opacity: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cooked img.d-lazyload {
|
||||
transition: opacity 0.4s 0.75s ease;
|
||||
}
|
||||
|
||||
.lightbox-wrapper {
|
||||
|
|
Loading…
Reference in New Issue