UNPKG

4.29 kBJavaScriptView Raw
1import Taro from '@tarojs/api';
2import { findDOM } from '../../utils/index.js';
3
4class TaroH5IntersectionObserver {
5 // selector 的容器节点
6 get container() {
7 const container = (this._component !== null
8 ? (findDOM(this._component) || document)
9 : document);
10 return container;
11 }
12 constructor(component, options = {}) {
13 // 选项
14 this._options = {
15 thresholds: [0],
16 initialRatio: 0,
17 observeAll: false
18 };
19 // 监控中的选择器
20 this._listeners = [];
21 // 用来扩展(或收缩)参照节点布局区域的边界
22 this._rootMargin = {};
23 // 是否已初始化
24 this._isInited = false;
25 this._component = component;
26 Object.assign(this._options, options);
27 }
28 createInst() {
29 // 去除原本的实例
30 this.disconnect();
31 const { left = 0, top = 0, bottom = 0, right = 0 } = this._rootMargin;
32 return new IntersectionObserver(entries => {
33 entries.forEach(entry => {
34 const _callback = this._getCallbackByElement(entry.target);
35 const result = {
36 boundingClientRect: entry.boundingClientRect,
37 intersectionRatio: entry.intersectionRatio,
38 intersectionRect: entry.intersectionRect,
39 relativeRect: entry.rootBounds || { left: 0, right: 0, top: 0, bottom: 0 },
40 // 使用时间戳而不是entry.time,跟微信小程序一致
41 time: Date.now(),
42 };
43 // web端会默认首次触发
44 if (!this._isInited && this._options.initialRatio <= Math.min.apply(Math, this._options.thresholds)) {
45 // 初始的相交比例,如果调用时检测到的相交比例与这个值不相等且达到阈值,则会触发一次监听器的回调函数。
46 return;
47 }
48 _callback && _callback.call(this, result);
49 });
50 this._isInited = true;
51 }, {
52 root: this._root,
53 rootMargin: [`${top}px`, `${right}px`, `${bottom}px`, `${left}px`].join(' '),
54 threshold: this._options.thresholds
55 });
56 }
57 disconnect() {
58 if (this._observerInst) {
59 let listener;
60 while ((listener = this._listeners.pop())) {
61 this._observerInst.unobserve(listener.element);
62 }
63 this._observerInst.disconnect();
64 }
65 }
66 observe(targetSelector, callback) {
67 // 同wx小程序效果一致,每个实例监听一个Selector
68 if (this._listeners.length)
69 return;
70 // 监听前没有设置关联的节点
71 if (!this._observerInst) {
72 console.warn('Intersection observer will be ignored because no relative nodes are found.');
73 return;
74 }
75 const nodeList = this._options.observeAll
76 ? this.container.querySelectorAll(targetSelector)
77 : [this.container.querySelector(targetSelector)];
78 Taro.nextTick(() => {
79 nodeList.forEach(element => {
80 if (!element)
81 return;
82 this._observerInst.observe(element);
83 this._listeners.push({ element, callback });
84 });
85 });
86 }
87 relativeTo(selector, margins) {
88 // 已设置observe监听后,重新关联节点
89 if (this._listeners.length) {
90 console.error('Relative nodes cannot be added after "observe" call in IntersectionObserver');
91 return this;
92 }
93 this._root = this.container.querySelector(selector) || null;
94 if (margins) {
95 this._rootMargin = margins;
96 }
97 this._observerInst = this.createInst();
98 return this;
99 }
100 relativeToViewport(margins) {
101 return this.relativeTo('.taro_page', margins);
102 }
103 _getCallbackByElement(element) {
104 const listener = this._listeners.find(listener => listener.element === element);
105 return listener ? listener.callback : null;
106 }
107}
108
109export { TaroH5IntersectionObserver };
110//# sourceMappingURL=IntersectionObserver.js.map