In this tutorial, we will discuss how to create a customer directive that will load images in lazy load manner also have an offset property to load loading distance.
Improve the performance of your Angular application by using a custom directive that loads images lazily. This directive allows you to delay loading images that are not visible on the screen, reducing the initial load time of your page and improving the user experience.
How to Create Custom Directive for Lazy Load Images?
To create a lazy load image directive in Angular 10 with an offset property to set how much before scroll the next image which is not in view should download, you can follow the below steps:
Step 1 – Create a new Angular directive using the CLI command:
ng generate directive lazy-load-image
Step 2 – In the generated lazy-load-image.directive.ts
file, import the ElementRef
and Renderer2
classes from @angular/core
.
Step 3 – Define an @Input
property called offset
to allow the user to set the number of pixels before the image is in view to start downloading.
@Input() offset: number = 100;
Step 4 – Create a HostListener
for the window:scroll
event that will check if the image is in the viewport and load the image if it is.
@HostListener('window:scroll', ['$event'])
onScroll(event) {
const rect = this.el.nativeElement.getBoundingClientRect();
const windowHeight = window.innerHeight;
const isImageVisible = rect.bottom >= 0 && rect.top - this.offset <= windowHeight;
if (isImageVisible) {
this.renderer.setAttribute(this.el.nativeElement, 'src', this.lazyLoadImage);
}
}
Step 5 – In the ngOnInit
lifecycle hook, set the src
attribute to the placeholder image.
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'src', this.placeholderImage);
}
Step 6 – Define two @Input
properties to allow the user to set the placeholder and lazy load images.
@Input() placeholderImage: string = 'assets/placeholder.png';
@Input() lazyLoadImage: string;
Step 7 – In the HTML template, add the lazy-load-image
directive to the <img>
tag and set the lazyLoadImage
property to the image URL.
<div *ngFor="let imageUrl of images">
<img lazy-load-image [lazyLoadImage]="imageUrl" [offset]="100">
</div>
The final lazy-load-image.directive.ts
file should look like this:
import {
Directive,
ElementRef,
Renderer2,
HostListener,
Input,
OnInit,
} from '@angular/core';
@Directive({
selector: '[lazy-load-image]',
})
export class LazyLoadImageDirective implements OnInit {
@Input() placeholderImage: string = 'assets/placeholder.png';
@Input() lazyLoadImage!: string;
@Input() offset: number = 100;
private isImageLoaded: boolean = false;
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnInit() {
const rect = this.el.nativeElement.getBoundingClientRect();
const windowHeight = window.innerHeight;
const isImageVisible =
rect.bottom >= 0 && rect.top - this.offset <= windowHeight;
if (isImageVisible) {
this.loadImage();
} else {
this.renderer.setAttribute(
this.el.nativeElement,
'src',
this.placeholderImage
);
}
}
@HostListener('window:scroll', ['$event'])
onScroll(event: any) {
if (!this.isImageLoaded) {
const rect = this.el.nativeElement.getBoundingClientRect();
const windowHeight = window.innerHeight;
const isImageVisible =
rect.bottom >= 0 && rect.top - this.offset <= windowHeight;
if (isImageVisible) {
this.loadImage();
}
}
}
private loadImage() {
this.renderer.setAttribute(
this.el.nativeElement,
'src',
this.lazyLoadImage
);
this.isImageLoaded = true;
}
}
In the component class, you can define the images object as follows for example:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
images: string[] = [];
constructor() {
for (let index = 0; index < 150; index++) {
this.images.push('https://picsum.photos/200');
}
}
}
Conclusion
With this custom directive, you can optimize the loading of images in your Angular 10 application and improve its performance. By delaying loading images that are not visible on the screen, you can reduce the initial load time of your page, improve the user experience, and boost your website’s search engine rankings.
Leave a Reply