iT邦幫忙

0

javascript: 錨點下滑+滾動點亮nav (ES6 Class)

  • 分享至 

  • xImage
  •  

使用方法

let a = new ClickScroll()
a.navBtns = [dom1, dom2, dom3] // 導覽列dom元素,陣列
a.targetEls = [dom4, dom5, dom6] // 目標dom元素,陣列
a.init() // 註冊點擊事件
a.exH = -100 // 額外距離,不一定要有
a.initScroll() // 註冊滾動事件,不一定要有
a.removeScroll() // 移除滾動事件,不一定要有

使用前,需先引入

class ClickScroll {
  exH = 0
  targetElsDistance = []
  constructor (navBtns, targetEls) {
    this.navBtns = navBtns
    this.targetEls = targetEls
  }

  // 為每個navBtn註冊click事件
  init () {
    this.navBtns.forEach( (btn, index) => {
      btn.addEventListener('click', (e) => {
        e.preventDefault()
        this.computeDistance()
        this.handleScroll(index)
      })
    })
  }

  // 註冊全域滾動事件
  initScroll () {
    window.addEventListener('scroll', this.detectScroll)
  }

  // 移除滾動事件
  removeScroll () {
    window.removeEventListener('scroll', this.detectScroll)
  }

  // 計算目標DOM元素們,距離元件最頂端距離
  // 最後,距離數值填入陣列
  computeDistance () {
    this.targetElsDistance.length = 0
    this.targetEls.forEach( el => {
      let distance = 0
      while (el && el.nodeName !== 'BODY') {
      distance += Number(el.offsetTop)
      el = el.offsetParent
      }
      this.targetElsDistance.push(distance)
    })
  }

  // 執行滾動,距離是targetElsDistance + exH
  handleScroll (index) {
    window.scrollTo({
      top: this.targetElsDistance[index] + this.exH,
      behavior: 'smooth',
    })
  }

  // 只有自己新增'active'的className,其餘DOM取消'active'
  addRemoveActive (target) {
    if (target.classList.contains('active')) return

    this.navBtns.forEach( btn => {
      btn.classList.remove('active')
    })
    target.classList.add('active')
  }

  detectScroll = () => {
    this.computeDistance()
    let arr = this.targetElsDistance
    let exH = this.exH - 5

    if (scrollY < arr[0] + exH) {
      this.navBtns.forEach( btn => {
        btn.classList.remove('active')
      })
      return
    }
    if (scrollY > arr[arr.length - 1] + exH) {
      this.addRemoveActive(this.navBtns[arr.length - 1])
      return
    }
    for (let i = 0; i < arr.length - 1; i++) {
      if (scrollY > arr[i] + exH && scrollY < arr[i+1] + exH) {
        this.addRemoveActive(this.navBtns[i])
      }
    }
  }
}

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言