|
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