|
16 | 16 | */ |
17 | 17 | export function observeMove(element, callback) { |
18 | 18 | let io = null; |
| 19 | + let timeout; |
19 | 20 |
|
20 | 21 | const root = document.documentElement; |
21 | 22 |
|
22 | 23 | function cleanup() { |
| 24 | + timeout && clearTimeout(timeout); |
23 | 25 | io && io.disconnect(); |
24 | 26 | io = null; |
25 | 27 | } |
@@ -52,27 +54,22 @@ export function observeMove(element, callback) { |
52 | 54 | let isFirstUpdate = true; |
53 | 55 |
|
54 | 56 | function handleObserve(entries) { |
55 | | - let ratio = entries[0].intersectionRatio; |
| 57 | + const ratio = entries[0].intersectionRatio; |
56 | 58 |
|
57 | 59 | if (ratio !== threshold) { |
58 | 60 | if (!isFirstUpdate) { |
59 | 61 | return refresh(); |
60 | 62 | } |
61 | 63 |
|
62 | | - // It's possible for the watched element to not be at perfect 1.0 visibility when we create |
63 | | - // the IntersectionObserver. This has a couple of causes: |
64 | | - // - elements being on partial pixels |
65 | | - // - elements being hidden offscreen (e.g., <html> has `overflow: hidden`) |
66 | | - // - delays: if your DOM change occurs due to e.g., page resize, you can see elements |
67 | | - // behind their actual position |
68 | | - // |
69 | | - // In all of these cases, refresh but with this lower ratio of threshold. When the element |
70 | | - // moves beneath _that_ new value, the user will get notified. |
71 | | - if (ratio === 0.0) { |
72 | | - ratio = 0.0000001; // Just needs to be non-zero |
| 64 | + if (!ratio) { |
| 65 | + // If the reference is clipped, the ratio is 0. Throttle the refresh |
| 66 | + // to prevent an infinite loop of updates. |
| 67 | + timeout = setTimeout(() => { |
| 68 | + refresh(false, 1e-7); |
| 69 | + }, 1000); |
| 70 | + } else { |
| 71 | + refresh(false, ratio); |
73 | 72 | } |
74 | | - |
75 | | - refresh(false, ratio); |
76 | 73 | } |
77 | 74 |
|
78 | 75 | isFirstUpdate = false; |
|
0 commit comments