根据 DOM id/class 把目标数据移动到可视区域

46 阅读1分钟
/**
 * @description 根据 id 移动到可视区域
 */
const getByIdMoveArea = id => {
  const oWrapper = document.querySelector('.list-call-wrapper .phone-wrapper')
  const childNodes = [...oWrapper.childNodes]
  const fId = id || this.fixedId
  const item = childNodes.find(e => e.id === fId)
  // item && (oWrapper.scrollTop = item.offsetTop);

  const fBottom = oWrapper.clientHeight + oWrapper.scrollTop - item.offsetHeight
  const fTop = oWrapper.scrollTop
  const target = item.offsetTop

  // 在可视区域不做操作
  if (target >= fTop && target <= fBottom) return

  clearInterval(oWrapper.timer)
  oWrapper.oldScrollTop = null
  if (target < fTop) {
    // 目标在可视区域上面
    oWrapper.timer = setInterval(() => startMove(oWrapper.scrollTop, item), 10)
  } else {
    const lastItemTop = childNodes[childNodes.length - 1].offsetTop
    const isArea = lastItemTop - item.offsetTop >= oWrapper.clientHeight
    // 目标在可视区域下面
    oWrapper.timer = setInterval(() => {
      // const cptNum = oWrapper.clientHeight + oWrapper.scrollTop - item.offsetHeight;
      const cptItem = isArea ? item : findAreaFirstItem(childNodes, oWrapper)
      startMove(oWrapper.scrollTop, cptItem)
    }, 10)
  }

  // 开始移动函数
  function startMove(target, item) {
    let speed = (item.offsetTop - target) / 8
    speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed)

    if (target === item.offsetTop || oWrapper.scrollTop === oWrapper.oldScrollTop) {
      clearInterval(oWrapper.timer)
    } else {
      oWrapper.oldScrollTop = oWrapper.scrollTop
      oWrapper.scrollTop = oWrapper.scrollTop + speed
    }
  }

  // 获取底部,刚好满整个可视区范围的第二条数据
  function findAreaFirstItem(childNodes, oWrapper) {
    let item = null
    for (let i = childNodes.length - 1; i >= 0; i--) {
      if (childNodes[i].offsetTop <= oWrapper.scrollHeight - oWrapper.clientHeight) {
        item = childNodes[i + 1]
        break
      }
    }

    return item
  }
}