列表頁曝光埋點實現

列表頁曝光埋點實現

以商品爲例

要求

  1. 商品一半以上出如今視窗中時 上報該行的商品
  2. 快速滑動過去的商品不上報
  3. 滑動過程當中若是一行商品一直未消失在視野中(一半以上),不能重複上報
  4. 滑出視野的商品,再次滑入視野時須要再次上報

分析

須要如下信息javascript

  1. 商品所在行的高度rowHeight(固定值)
  2. 商品的可視區域的高度contentHeight(半固定值,不考慮瀏覽器的resize)
  3. 可視區域距離視窗頂部的高度headHeight(固定值)
  4. content的滾動高度(與scroll事件相關,考慮到滑動快時不觸發上報,須要throttle)

實現

/**
 * 滾動事件處理
 * @param {number} headHeight content區域距離頂部的高度
 * @param {number} rowHeight 每一行的高度
 * @returns {Function}
 */
export function handleScroll(headHeight, rowHeight) {
  let lastActive = []
  let deactived = []
  /**
   * @param   {number} contentTop 區域的top值
   * @return  {Array}  當前活躍的的行
   */
  return function(contentTop) {
    let topDiff = contentTop - headHeight
    // 可視區域高度
    let visibleHeight =
      window.innerHeight - (topDiff <= 0 ? headHeight : contentTop)
    /**
     * 當前能顯示的行數
     * 顯露一半就須要上報 則使用四捨五入
     */
    let rowCount = Math.round(visibleHeight / rowHeight)
    /**
     * 獲取當前顯示的下標
     */
    let index = topDiff > 0 ? 0 : Math.round(-topDiff / rowHeight)
    let _active = Array.from({ length: rowCount }).reduce(
      (pre, cur, i) => pre.concat(index + i),
      []
    )
    /**
     * 以前上報過,未從屏幕上消失過的 不上報
     * 以前上報過,從屏幕中消失又出現的 上報
     */
    let active = _active.filter(
      v => !lastActive.includes(v) || deactived.includes(v)
    )
    /**
     * 收集非活躍狀態的行,只收集滾上去的元素,active下面的行屬於待活躍狀態,因爲和行的總數相關(商品的總行數知道與否不影響上報),會額外增長沒必要要的工做 因此此處不作考慮
     */
    deactived = Array.from({ length: index }).map((val, i) => i)
    /**
     * 上次活躍的行,用來避免重複上報
     */
    lastActive = [].concat(deactived).concat(_active)
    return {
      lastActive,
      active,
      deactived
    }
  }
}

圖示

5bfca0967daa9

使用

let target = document.getElementById('wrapper')
let onScroll = handleScroll(100, 420)
let _scroll = _.throttle(function(){
 let row = onScroll(target.getBoundingClientRect().y)
 // 此時row.active就是須要上報的行的下標,active可能爲空數組
 ...
}, 1000)
target.addEventListener('scroll', _scroll)
相關文章
相關標籤/搜索