requestComponentObserver.ts 2.6 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1
import { getCustomDataset } from '@dcloudio/uni-shared'
fxy060608's avatar
fxy060608 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import { initIntersectionObserverPolyfill } from './intersection-observer'

export interface RequestComponentObserverOptions {
  selector?: string
  rootMargin?: string
  relativeToSelector?: string
}

function normalizeRect(rect: DOMRect) {
  const { bottom, height, left, right, top, width } = rect || {}
  return {
    bottom,
    height,
    left,
    right,
    top,
    width,
  }
}

D
DCloud_LXH 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// 在相交比很小的情况下,Chrome会返回相交为0
function rectifyIntersectionRatio(entrie: IntersectionObserverEntry) {
  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
}

fxy060608's avatar
fxy060608 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
export function requestComponentObserver(
  $el: HTMLElement,
  options: UniApp.CreateIntersectionObserverOptions &
    RequestComponentObserverOptions,
  callback: WechatMiniprogram.IntersectionObserverObserveCallback
) {
  // 为了摇树优化,不直接引入该polyfill
  initIntersectionObserverPolyfill()
  const root = options.relativeToSelector
    ? $el.querySelector(options.relativeToSelector)
    : null
  const intersectionObserver = new IntersectionObserver(
    (entries) => {
      entries.forEach((entrie) => {
        callback({
D
DCloud_LXH 已提交
52
          intersectionRatio: rectifyIntersectionRatio(entrie),
fxy060608's avatar
fxy060608 已提交
53 54 55 56
          intersectionRect: normalizeRect(entrie.intersectionRect),
          boundingClientRect: normalizeRect(entrie.boundingClientRect),
          relativeRect: normalizeRect(entrie.rootBounds!),
          time: Date.now(),
fxy060608's avatar
fxy060608 已提交
57 58
          dataset: getCustomDataset(entrie.target as HTMLElement),
          id: entrie.target.id,
fxy060608's avatar
fxy060608 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
        })
      })
    },
    {
      root,
      rootMargin: options.rootMargin,
      threshold: options.thresholds,
    }
  )
  if (options.observeAll) {
    ;(intersectionObserver as any).USE_MUTATION_OBSERVER = true
    const nodeList = $el.querySelectorAll(options.selector!)
    for (let i = 0; i < nodeList.length; i++) {
      intersectionObserver.observe(nodeList[i])
    }
  } else {
    ;(intersectionObserver as any).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.`
      )
    } else {
      intersectionObserver.observe(el)
    }
  }
  return intersectionObserver
}