iT邦幫忙

0

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

  • 分享至 

  • 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() // 移除滾動事件,不一定要有

使用前,需先引入

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

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

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

// 移除滾動事件
ClickScroll.prototype.removeScroll = function () {
  window.removeEventListener('scroll', ClickScroll.prototype.detectScroll)
}

// 計算目標DOM元素們,距離元件最頂端距離
// 最後,距離數值填入陣列
ClickScroll.prototype.computeDistance = function () {
  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
ClickScroll.prototype.handleScroll = function (index) {
  window.scrollTo({
    top: this.targetElsDistance[index] + this.exH,
    behavior: 'smooth',
  })
}

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

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

ClickScroll.prototype.detectScroll = function () {
  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) }}
直播中

尚未有邦友留言

立即登入留言