clone of github.com/decent-newsroom/newsroom
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

55 lines
1.5 KiB

import { Controller } from '@hotwired/stimulus';
/*
* Image Loader Controller
* Defers loading images until they scroll nearby using Intersection Observer
*/
export default class extends Controller {
static targets = ['image'];
connect() {
// Create intersection observer to load images when nearby
this.observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadImage(entry.target);
this.observer.unobserve(entry.target);
}
});
},
{
root: null,
rootMargin: '200px', // Start loading 200px before image enters viewport
threshold: 0
}
);
// Start observing the image
this.observer.observe(this.imageTarget);
}
disconnect() {
if (this.observer) {
this.observer.disconnect();
}
}
loadImage(img) {
const src = img.getAttribute('data-src');
if (!src) return;
// Set up load event before setting src
img.addEventListener('load', () => {
img.classList.add('loaded');
}, { once: true });
// Start loading the image
img.src = src;
// If image is already cached, it might load instantly
if (img.complete) {
img.classList.add('loaded');
}
}
}