/
intersection-listener.ts
49 lines (38 loc) 路 1.44 KB
/
intersection-listener.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { empty, Observable, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { Attributes } from '../types';
import { isWindowDefined } from '../util';
type ObserverOptions = {
root?: Element;
rootMargin?: string;
};
const observers = new WeakMap<Element | {}, IntersectionObserver>();
const intersectionSubject = new Subject<IntersectionObserverEntry>();
function loadingCallback(entrys: IntersectionObserverEntry[]) {
entrys.forEach(entry => intersectionSubject.next(entry));
}
export const getIntersectionObserver = (attributes: Attributes): Observable<IntersectionObserverEntry> => {
if (!attributes.scrollContainer && !isWindowDefined()) {
return empty();
}
const options: ObserverOptions = {
root: attributes.scrollContainer
};
if (attributes.offset) {
options.rootMargin = `${attributes.offset}px`;
}
const scrollContainer = attributes.scrollContainer || window;
let observer = observers.get(scrollContainer);
if (!observer) {
observer = new IntersectionObserver(loadingCallback, options);
observers.set(scrollContainer, observer);
}
observer.observe(attributes.element);
return Observable.create((obs: Subject<IntersectionObserverEntry>) => {
const subscription = intersectionSubject.pipe(filter(entry => entry.target === attributes.element)).subscribe(obs);
return () => {
subscription.unsubscribe();
observer!.unobserve(attributes.element);
};
});
};