Files
bizmatch-project/bizmatch/src/app/directives/lazy-load-image.directive.ts

91 lines
2.5 KiB
TypeScript

import { Directive, ElementRef, Input, OnInit, Renderer2 } from '@angular/core';
@Directive({
selector: 'img[appLazyLoad]',
standalone: true
})
export class LazyLoadImageDirective implements OnInit {
@Input() appLazyLoad: string = '';
@Input() placeholder: string = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300"%3E%3Crect fill="%23f3f4f6" width="400" height="300"/%3E%3C/svg%3E';
private observer: IntersectionObserver | null = null;
constructor(
private el: ElementRef<HTMLImageElement>,
private renderer: Renderer2
) {}
ngOnInit() {
// Add loading="lazy" attribute for native lazy loading
this.renderer.setAttribute(this.el.nativeElement, 'loading', 'lazy');
// Set placeholder while image loads
if (this.placeholder) {
this.renderer.setAttribute(this.el.nativeElement, 'src', this.placeholder);
}
// Add a CSS class for styling during loading
this.renderer.addClass(this.el.nativeElement, 'lazy-loading');
// Use Intersection Observer for enhanced lazy loading
if ('IntersectionObserver' in window) {
this.observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
this.loadImage();
}
});
},
{
rootMargin: '50px' // Start loading 50px before image enters viewport
}
);
this.observer.observe(this.el.nativeElement);
} else {
// Fallback for browsers without Intersection Observer
this.loadImage();
}
}
private loadImage() {
const img = this.el.nativeElement;
const src = this.appLazyLoad || img.getAttribute('data-src');
if (src) {
// Create a new image to preload
const tempImg = new Image();
tempImg.onload = () => {
this.renderer.setAttribute(img, 'src', src);
this.renderer.removeClass(img, 'lazy-loading');
this.renderer.addClass(img, 'lazy-loaded');
// Disconnect observer after loading
if (this.observer) {
this.observer.disconnect();
}
};
tempImg.onerror = () => {
console.error('Failed to load image:', src);
this.renderer.removeClass(img, 'lazy-loading');
this.renderer.addClass(img, 'lazy-error');
if (this.observer) {
this.observer.disconnect();
}
};
tempImg.src = src;
}
}
ngOnDestroy() {
if (this.observer) {
this.observer.disconnect();
}
}
}