import * as React from "react"; import { ControlProps } from "../util"; export interface LazyImageProps extends ControlProps { src: string; alt: string; title?: string; loadingElement?: JSX.Element; } let observer: IntersectionObserver; export const LazyImage = (props: LazyImageProps) => { const { id, className, role, src, alt, title, ariaLabel, ariaHidden, ariaDescribedBy, loadingElement, } = props; initObserver(); let imageRef: HTMLImageElement; const handleImageRef = (ref: HTMLImageElement) => { if (!ref) return; if (imageRef) observer.unobserve(imageRef); imageRef = ref; observer.observe(ref); } return
{loadingElement ? loadingElement :
}
{alt}
} function initObserver() { if (observer) return; const config = { // If the image gets within 50px in the Y axis, start the download. rootMargin: '50px 0px', threshold: 0.01 }; const onIntersection: IntersectionObserverCallback = (entries) => { entries.forEach(entry => { // Are we in viewport? if (entry.intersectionRatio > 0) { // Stop watching and load the image observer.unobserve(entry.target); const url = entry.target.getAttribute("data-src"); (entry.target as HTMLImageElement).src = url; const image = entry.target as HTMLImageElement; image.src = url; image.onload = () => { image.parentElement.classList.add("loaded"); image.parentElement.classList.remove("error"); } image.onerror = () => { image.parentElement.classList.add("error") image.parentElement.classList.remove("loaded") } } }) } observer = new IntersectionObserver(onIntersection, config); }