SEO/AEO, Farb schema, breadcrumbs
This commit is contained in:
90
bizmatch/src/app/directives/lazy-load-image.directive.ts
Normal file
90
bizmatch/src/app/directives/lazy-load-image.directive.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user