Skip to content

Instantly share code, notes, and snippets.

@mhartington
Created January 6, 2019 00:35
Show Gist options
  • Save mhartington/eb4679561949f537a991e6ca656449eb to your computer and use it in GitHub Desktop.
Save mhartington/eb4679561949f537a991e6ca656449eb to your computer and use it in GitHub Desktop.
import {
Component,
OnInit,
Input,
ViewChild,
ElementRef,
HostBinding
} from '@angular/core';
@Component({
selector: 'lazy-img',
template: `
<div class="placeholder">
<img #lazyImage decoding="async" [alt]="alt" />
</div>
`,
styles: [
`
.placeholder {
width: 100%;
height: 100%;
background: #808080;
transition: background 500ms ease-out;
}
img {
opacity: 0;
transition: opacity 1000ms ease-in;
object-fit: cover;
height: 100%;
}
:host(.loaded) {
.placeholder {
background: #fff;
}
img {
opacity: 1;
}
}
`
]
})
export class LazyImgComponent {
observer: IntersectionObserver;
@Input() src = '';
@Input() alt = '';
@HostBinding('class.loaded') isLoaded: boolean = false;
@ViewChild('lazyImage') lazyImage: ElementRef;
constructor() {}
ngAfterViewInit() {
const options: IntersectionObserverInit = {
root: this.lazyImage.nativeElement.closest('ion-content')
};
if ('IntersectionObserver' in window) {
this.observer = new IntersectionObserver(
this.onObserve.bind(this),
options
);
this.observer.observe(this.lazyImage.nativeElement);
} else {
setTimeout(() => this.preload(this.lazyImage.nativeElement), 200);
}
}
ngOnDestroy() {
this.observer.disconnect();
}
onObserve(data): IntersectionObserverCallback {
if (data[0].isIntersecting) {
console.log('is in');
this.preload(data[0].target).then(() => {
this.observer.disconnect();
});
}
return;
}
applyImage(target: HTMLImageElement, src) {
return new Promise((resolve, reject) => {
target.src = src;
resolve();
});
}
fetchImage(url) {
return new Promise((resolve, reject) => {
let image = new Image();
image.src = url;
image.onload = resolve;
image.onerror = reject;
});
}
preload(targetEl) {
return this.fetchImage(this.src)
.then(() => this.applyImage(targetEl, this.src))
.then(() => (this.isLoaded = true));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment