From f1c45043aa6b6968390bb69dd875957df4cc4509 Mon Sep 17 00:00:00 2001 From: markuskr Date: Sat, 17 Nov 2018 22:04:37 +0100 Subject: [PATCH 1/2] First version using IntersectionObserver --- visibility-sensor.js | 79 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/visibility-sensor.js b/visibility-sensor.js index 067b3c4..a52a754 100644 --- a/visibility-sensor.js +++ b/visibility-sensor.js @@ -17,6 +17,31 @@ function normalizeRect(rect) { return rect; } +function isIntersectionObserverSupported() { + if ( + "IntersectionObserver" in window && + "IntersectionObserverEntry" in window && + "intersectionRatio" in window.IntersectionObserverEntry.prototype + ) { + // Minimal polyfill for Edge 15's lack of `isIntersecting` + // See: https://github.com/w3c/IntersectionObserver/issues/211 + if (!("isIntersecting" in window.IntersectionObserverEntry.prototype)) { + Object.defineProperty( + window.IntersectionObserverEntry.prototype, + "isIntersecting", + { + get: function() { + return this.intersectionRatio > 0; + } + } + ); + } + return true; + } else { + return false; + } +} + export default class VisibilitySensor extends React.Component { static defaultProps = { active: true, @@ -75,7 +100,6 @@ export default class VisibilitySensor extends React.Component { constructor(props) { super(props); - this.state = { isVisible: null, visibilityRect: {} @@ -152,6 +176,17 @@ export default class VisibilitySensor extends React.Component { }; startWatching = () => { + if (isIntersectionObserverSupported()) { + this.observer = this.createIntersectionObserver( + this.props.onChange, + this.props.partialVisibility, + this.props.offset, + this.props.containment + ); + this.observer.observe(this.node); + return; + } + if (this.debounceCheck || this.interval) { return; } @@ -183,6 +218,11 @@ export default class VisibilitySensor extends React.Component { }; stopWatching = () => { + if (this.observer) { + this.observer.unobserve(this.node); + this.observer.disconnect(); + return; + } if (this.debounceCheck) { // clean up event listeners and their debounce callers for (let debounceEvent in this.debounceCheck) { @@ -215,6 +255,43 @@ export default class VisibilitySensor extends React.Component { }; } + createIntersectionObserver = ( + onChange, + partialVisibility, + offset, + containment + ) => { + if (isIntersectionObserverSupported()) { + var callback = function(entries) { + entries.forEach(entry => { + var shape = entry.isIntersecting + ? { + top: entry.intersectionRect.top, + bottom: entry.intersectionRect.bottom, + left: entry.intersectionRect.left, + right: entry.intersectionRect.right + } + : undefined; + + typeof onChange === "function" && + onChange(entry.isIntersecting, shape); + }); + }; + console.log(containment); + var options = { + threshold: partialVisibility ? 0 : 1, + root: containment, + rootMargin: + partialVisibility && typeof offset === "object" + ? `${offset.top}px ${offset.right}px ${offset.bottom}px ${ + offset.left + }px` + : "0px" + }; + return new IntersectionObserver(callback, options); + } + }; + /** * Check if the element is within the visible viewport */ From d9b57a3aecae2d5bae6d2f1f7006583959a20db2 Mon Sep 17 00:00:00 2001 From: markuskr Date: Tue, 20 Nov 2018 22:33:47 +0100 Subject: [PATCH 2/2] Remove debug console.log --- visibility-sensor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visibility-sensor.js b/visibility-sensor.js index a52a754..8783ee7 100644 --- a/visibility-sensor.js +++ b/visibility-sensor.js @@ -277,7 +277,7 @@ export default class VisibilitySensor extends React.Component { onChange(entry.isIntersecting, shape); }); }; - console.log(containment); + var options = { threshold: partialVisibility ? 0 : 1, root: containment,