diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e31edc..519e3d58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ way to update this template, but currently, we follow a pattern: --- +## v1.2.1 +* [fix] Lazy load map only if the map is near current viewport. + [#871](https://github.com/sharetribe/flex-template-web/pull/871) + ## v1.2.0 * [change] Use Google's static map on ListingPage. This is a reaction to pricing change of Google Maps APIs. diff --git a/src/containers/ListingPage/ListingPage.css b/src/containers/ListingPage/ListingPage.css index 7a745f7a..d28bbc5e 100644 --- a/src/containers/ListingPage/ListingPage.css +++ b/src/containers/ListingPage/ListingPage.css @@ -531,8 +531,9 @@ height: calc(100vh - 193px); width: 100%; - /* Static map: max-width is 640px */ + /* Static map: dimensions are 640px */ max-width: 640px; + max-height: 640px; background-color: #eee; @media (--viewportMedium) { diff --git a/src/util/contextHelpers.js b/src/util/contextHelpers.js index 40f99e1e..03d1c261 100644 --- a/src/util/contextHelpers.js +++ b/src/util/contextHelpers.js @@ -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); @@ -95,9 +99,9 @@ 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.handleWindowResize = throttle(this.handleWindowResize.bind(this), THROTTLE_WAIT_MS); + this.isElementNearViewport = this.isElementNearViewport.bind(this); + this.setDimensions = this.setDimensions.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;