|
export default class LazyLoader {
|
|
constructor(options = {}) {
|
|
this.threshold = options.threshold || 0.1;
|
|
this.rootMargin = options.rootMargin || '50px';
|
|
this.observer = null;
|
|
this.logger = options.logger || null;
|
|
this._setup();
|
|
}
|
|
|
|
_setup() {
|
|
this.observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
this._loadElement(entry.target);
|
|
this.observer.unobserve(entry.target);
|
|
}
|
|
});
|
|
},
|
|
{
|
|
threshold: this.threshold,
|
|
rootMargin: this.rootMargin
|
|
}
|
|
);
|
|
}
|
|
|
|
observe(element) {
|
|
if (!element) return;
|
|
this.observer.observe(element);
|
|
}
|
|
|
|
unobserve(element) {
|
|
if (!element) return;
|
|
this.observer.unobserve(element);
|
|
}
|
|
|
|
observeAll(selector) {
|
|
document.querySelectorAll(selector).forEach((el) => {
|
|
this.observe(el);
|
|
});
|
|
}
|
|
|
|
_loadElement(element) {
|
|
try {
|
|
if (element.dataset.src) {
|
|
element.src = element.dataset.src;
|
|
element.removeAttribute('data-src');
|
|
this.logger?.debug(`Lazy loaded image: ${element.src}`);
|
|
}
|
|
|
|
if (element.dataset.backgroundImage) {
|
|
element.style.backgroundImage = `url(${element.dataset.backgroundImage})`;
|
|
element.removeAttribute('data-background-image');
|
|
this.logger?.debug(`Lazy loaded background image`);
|
|
}
|
|
|
|
element.classList.add('loaded');
|
|
} catch (error) {
|
|
this.logger?.error('Failed to lazy load element', error);
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
if (this.observer) {
|
|
this.observer.disconnect();
|
|
}
|
|
}
|
|
}
|