寫一個wow.js

  • 86
  • 0
  • 2022-01-23

老大說希望我們都自己手寫,所以這次就來寫一個自己的wow.js

知識點

  1. window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop
  2. getAttribute
  3. document.documentElement.clientHeight
  4. Es6 class

思路

  1. 算出滾動條可是區下方的y點位置
  2. 當元素最上方的y點位置小魚滾動條y點位置時觸發屬性上的class
  3. 預設加上trigger的元素為visibility:hidden
#.js

export default class ScrollTriggerAnimation {
  constructor (options = {}) {
    // 修正this指向
    this.scrollFunc = this.scrollFunc.bind(this)
    this.remove = this.remove.bind(this)
  }

  // 初始化
  init () {
    // 添加此套件css
    this.addStyleSheet()
    // 監聽事件
    document.addEventListener('scroll', this.scrollFunc)
  }

  // 移除事件監聽
  remove () {
    window.removeEventListener('scroll', this.scrollFunc)
  }

  // 主要邏輯
  scrollFunc () {
    const triggerDoms = document.querySelectorAll('.trigger')
    if (!triggerDoms.length) return
    triggerDoms.forEach(dom => {
      const time = this.getDelayAttribute(dom) || 0
      const currentBottomPos = this.getCurrentBottomPos()
      const classes = this.getClassesAttribute(dom)
      if (dom.style.visibility === 'visible') return
      // 當dom進入可視區最下方時加上自定義屬性上的className
      if (currentBottomPos > dom.getBoundingClientRect().top + document.documentElement.scrollTop) {
        window.setTimeout(() => {
          dom.style.visibility = 'visible'
          classes.forEach(className => {
            dom.classList.add(className)
          })
        }, time)
      }
    })
  }

  // 可視區Y軸最下方位置
  getCurrentBottomPos () {
    return this.getScrollTop() + document.documentElement.clientHeight
  }

  // 兼容
  getScrollTop () {
    return Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop)
  }

  // 獲取dom自定義屬性
  getDelayAttribute (dom) {
    return dom.getAttribute('trigger-delay')
  }

  // 獲取dom自定義屬性
  getClassesAttribute (dom) {
    return dom.getAttribute('trigger-classes').split(',')
  }

  // 添加css
  addStyleSheet () {
    let styleElement = null
    styleElement = document.createElement('style')
    styleElement.type = 'text/css'
    document.getElementsByTagName('head')[0].appendChild(styleElement)
    styleElement.appendChild(document.createTextNode('.trigger {visibility: hidden }'))
  }
}

#引入
import ScrollTriggerAnimation from './plugins/scrollTrigger'
new ScrollTriggerAnimation({}).init()

#使用
   <li    
   		trigger-delay="1000" //延遲時間
        trigger-classes="animate__slideInUp,animate__animated" //觸發時要加上的class
        class="trigger" //這個一定要加預設為visibility:hidden
   >