Lazy load component if it's vertically near viewport

This commit is contained in:
Vesa Luusua 2018-07-19 17:19:54 +03:00
parent 5a920359c4
commit d5e4cacc7f

View file

@ -87,6 +87,10 @@ export const lazyLoadWithDimensions = (Component, options) => {
// First render default wait after mounting (small wait for styled paint)
const RENDER_WAIT_MS = 100;
// Scrolling and other events that affect to viewport location have this safety margin
// for lazy loading
const NEAR_VIEWPORT_MARGIN = 50;
class LazyLoadWithDimensionsComponent extends ReactComponent {
constructor(props) {
super(props);
@ -96,8 +100,8 @@ export const lazyLoadWithDimensions = (Component, options) => {
this.state = { width: 0, height: 0 };
this.handleWindowResize = this.handleWindowResize.bind(this);
this.isElementInViewport = this.isElementInViewport.bind(this);
this.setDimensions = throttle(this.setDimensions.bind(this), THROTTLE_WAIT_MS);
this.isElementNearViewport = this.isElementNearViewport.bind(this);
}
componentDidMount() {
@ -106,8 +110,8 @@ export const lazyLoadWithDimensions = (Component, options) => {
window.addEventListener('orientationchange', this.handleWindowResize);
this.defaultRenderTimeout = window.setTimeout(() => {
if (this.isElementInViewport()) {
this.handleWindowResize();
if (this.isElementNearViewport(0)) {
this.setDimensions();
}
}, RENDER_WAIT_MS);
}
@ -120,7 +124,9 @@ export const lazyLoadWithDimensions = (Component, options) => {
}
handleWindowResize() {
this.setDimensions();
if (this.isElementNearViewport(NEAR_VIEWPORT_MARGIN)) {
this.setDimensions();
}
}
setDimensions() {
@ -130,15 +136,14 @@ export const lazyLoadWithDimensions = (Component, options) => {
});
}
isElementInViewport() {
isElementNearViewport(safetyBoundary) {
if (this.element) {
const rect = this.element.getBoundingClientRect();
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
(rect.top >= 0 && rect.top <= viewportHeight + safetyBoundary) ||
(rect.bottom >= -1 * safetyBoundary && rect.bottom <= viewportHeight)
);
}
return false;