import 'intersection-observer'
|
|
import {
|
getTargetDataset
|
} from 'uni-helpers/index'
|
|
import {
|
findElm
|
} from './util'
|
|
function getRect (rect) {
|
return {
|
bottom: rect.bottom,
|
height: rect.height,
|
left: rect.left,
|
right: rect.right,
|
top: rect.top,
|
width: rect.width
|
}
|
}
|
|
// 在相交比很小的情况下,Chrome会返回相交为0
|
function rectifyIntersectionRatio (entrie) {
|
const {
|
intersectionRatio,
|
boundingClientRect: { height: overAllHeight, width: overAllWidth },
|
intersectionRect: { height: intersectionHeight, width: intersectionWidth }
|
} = entrie
|
|
if (intersectionRatio !== 0) return intersectionRatio
|
|
return intersectionHeight === overAllHeight
|
? intersectionWidth / overAllWidth
|
: intersectionHeight / overAllHeight
|
}
|
|
const intersectionObservers = {}
|
|
export function requestComponentObserver ({
|
reqId,
|
component,
|
options
|
}, pageId) {
|
let pageVm
|
if (pageId._isVue) {
|
pageVm = pageId
|
} else {
|
const pages = getCurrentPages() // 跨平台时,View 层也应该实现该方法,举例 App 上,View 层的 getCurrentPages 返回长度为1的当前页面数组
|
const page = pages.find(page => page.$page.id === pageId)
|
if (!page) {
|
throw new Error(`Not Found:Page[${pageId}]`)
|
}
|
pageVm = page.$vm
|
}
|
const $el = findElm(component, pageVm)
|
const root = options.relativeToSelector ? $el.querySelector(options.relativeToSelector) : null
|
const intersectionObserver = intersectionObservers[reqId] = new IntersectionObserver((entries, observer) => {
|
entries.forEach(entrie => {
|
UniViewJSBridge.publishHandler('onRequestComponentObserver', {
|
reqId,
|
res: {
|
intersectionRatio: rectifyIntersectionRatio(entrie),
|
intersectionRect: getRect(entrie.intersectionRect),
|
boundingClientRect: getRect(entrie.boundingClientRect),
|
relativeRect: getRect(entrie.rootBounds),
|
time: Date.now(),
|
dataset: getTargetDataset(entrie.target),
|
id: entrie.target.id
|
}
|
})
|
})
|
}, {
|
root,
|
rootMargin: options.rootMargin,
|
threshold: options.thresholds
|
})
|
if (options.observeAll) {
|
intersectionObserver.USE_MUTATION_OBSERVER = true
|
Array.prototype.map.call($el.querySelectorAll(options.selector), el => {
|
if (!el) {
|
console.warn(`Node ${options.selector} is not found. Intersection observer will not trigger.`)
|
return
|
}
|
intersectionObserver.observe(el)
|
})
|
} else {
|
intersectionObserver.USE_MUTATION_OBSERVER = false
|
const el = $el.querySelector(options.selector)
|
if (!el) {
|
console.warn(`Node ${options.selector} is not found. Intersection observer will not trigger.`)
|
return
|
}
|
intersectionObserver.observe(el)
|
}
|
}
|
|
export function destroyComponentObserver ({
|
reqId
|
}) {
|
const intersectionObserver = intersectionObservers[reqId]
|
if (intersectionObserver) {
|
intersectionObserver.disconnect()
|
delete intersectionObservers[reqId]
|
UniViewJSBridge.publishHandler('onRequestComponentObserver', {
|
reqId,
|
reqEnd: true
|
})
|
}
|
}
|