滾動樓層導航定位

動態樓層導航

目錄

動態樓層導航

頁面佈局

數據模型

滾動事件監聽

監聽窗口滾動樓層導航動態定位

設置樓層導航事件驅動方法

設置樓層向上滾動

設置樓層向下滾動

完整代碼


在vue中使用v-for動態渲染樓層和樓層導航,然後使用原生JavaScript實現樓層導航動態更新與樓層滾動定位

1、頁面初始化時定位首個樓層

2、頁面滾動樓層導航自動定位到相應的樓層並高亮顯示

3、鼠標點擊樓層導航時,當前樓層導航高亮顯示,並且頁面自動滾動到相應的樓層

滾動樓層導航定位示例地址

頁面佈局

<template>
  <div class="floor-warpper">
    <section class="floor-nav" id="floorNavList">
      <ul class="nav-list">
        <li
          class="nav-list-item"
          v-for="(item, index) in floorList"
          :key="item.id"
          @click="setFloorNavMountClick(index)"
        >{{ item.name }}</li>
      </ul>
    </section>
    <section
      class="floor-item"
      v-for="item in floorList"
      :key="item.id">
      <div class="floor-item-box">
        <h3>{{ item.name }}</h3>
      </div>
    </section>
  </div>
</template>

數據模型

export default {
  name: 'IFloor',
  data () {
    return {
      element: {
        nav_item: null,
        floor_item: null
      },
      timer: null,
      floorList: [
        { id: 1, name: 'F1' },
        { id: 2, name: 'F2' },
        { id: 3, name: 'F3' },
        { id: 4, name: 'F4' },
        { id: 5, name: 'F5' },
        { id: 6, name: 'F6' }
      ]
    }
  }
}

滾動事件監聽

export default {
  mounted () {
    this.element = {
      nav_item: document.getElementsByClassName('nav-list-item'),
      floor_item: document.getElementsByClassName('floor-item')
    }
    this.element.nav_item[0].classList.add('active')
    window.addEventListener('scroll', this.floorSrcollEventListener)
  },
  beforeDestroy () {
    window.removeEventListener('scroll', this.floorSrcollEventListener)
  },
}

監聽窗口滾動樓層導航動態定位

export default {
  methods: {
    /**
     * 監聽窗口滾動樓層導航動態定位
     */
    floorSrcollEventListener () {
      const { nav_item, floor_item } = this.element
      const window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
      for (let i = 0, len = floor_item.length; i < len; i++) {
        let floor_offsetTop = floor_item[i].offsetTop - floor_item[0].offsetTop
        if (window_scrollTop >= floor_offsetTop) {
          for (let n = 0, len = nav_item.length; n < len; n++) {
            const current_classList = nav_item[n].classList
            i === n
              ? current_classList.add('active')
              : current_classList.remove('active')
          }
        }
      }
    }
  }
}

設置樓層導航事件驅動方法

export default {
  methods: {
    /**
     * 設置樓層導航事件驅動方法
     * @param {Number} index  樓層下標
     */
    setFloorNavMountClick (index) {
      const { floor_item } = this.element
      const floor_offsetTop = floor_item[index].offsetTop - floor_item[0].offsetTop,
        window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
        timer = {
          step: 60,
          times: 16,
          FLOOR_OFFSETTOP: floor_offsetTop,
        }
      if (window_scrollTop > floor_offsetTop) {
        this.setFloorScrollArrowUp(timer)
      } else if (window_scrollTop == floor_offsetTop) {
        return false
      } else {
        this.setFloorScrollArrowDown(timer)
      }
    }
  }
}

設置樓層向上滾動

export default {
  methods: {
    /**
     * 設置樓層向上滾動
     * @param {Object} timer 定時器配置
     */
    setFloorScrollArrowUp (timer) {
      clearInterval(this.timer)
      this.timer = setInterval(() => {
        let window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        if (window_scrollTop <= timer.FLOOR_OFFSETTOP) {
          document.documentElement.scrollTop = timer.FLOOR_OFFSETTOP
          document.body.scrollTop = timer.FLOOR_OFFSETTOP
          clearInterval(this.timer)
        } else {
          document.documentElement.scrollTop = window_scrollTop - timer.step
          document.body.scrollTop = window_scrollTop - timer.step
        }
      }, timer.times)
    }
  }
}

設置樓層向下滾動

export default {
  methods: {
    /**
     * 設置樓層向下滾動
     * @param {Object} timer 定時器配置
     */
    setFloorScrollArrowDown (timer) {
      clearInterval(this.timer)
      this.timer = setInterval(() => {
        let window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        if (window_scrollTop >= timer.FLOOR_OFFSETTOP) {
          document.documentElement.scrollTop = timer.FLOOR_OFFSETTOP
          document.body.scrollTop = timer.FLOOR_OFFSETTOP
          clearInterval(this.timer)
        } else {
          document.documentElement.scrollTop = window_scrollTop + timer.step
          document.body.scrollTop = window_scrollTop - timer.step
        }
      }, timer.times)
    }
  }
}

 

完整代碼

<template>
  <div class="floor-warpper">
    <section class="floor-nav" id="floorNavList">
      <ul class="nav-list">
        <li
          class="nav-list-item"
          v-for="(item, index) in floorList"
          :key="item.id"
          @click="setFloorNavMountClick(index)"
        >{{ item.name }}</li>
      </ul>
    </section>
    <section
      class="floor-item"
      v-for="item in floorList"
      :key="item.id">
      <div class="floor-item-box">
        <h3>{{ item.name }}</h3>
      </div>
    </section>
  </div>
</template>

<script>
export default {
  name: 'IFloor',
  data () {
    return {
      element: {
        nav_item: null,
        floor_item: null
      },
      timer: null,
      floorList: [
        { id: 1, name: 'F1' },
        { id: 2, name: 'F2' },
        { id: 3, name: 'F3' },
        { id: 4, name: 'F4' },
        { id: 5, name: 'F5' },
        { id: 6, name: 'F6' }
      ]
    }
  },
  mounted () {
    this.element = {
      nav_item: document.getElementsByClassName('nav-list-item'),
      floor_item: document.getElementsByClassName('floor-item')
    }
    this.element.nav_item[0].classList.add('active')
    window.addEventListener('scroll', this.floorSrcollEventListener)
  },
  beforeDestroy () {
    window.removeEventListener('scroll', this.floorSrcollEventListener)
  },
  methods: {
    /**
     * 設置樓層導航事件驅動方法
     * @param {Number} index  樓層下標
     */
    setFloorNavMountClick (index) {
      const { floor_item } = this.element
      const floor_offsetTop = floor_item[index].offsetTop - floor_item[0].offsetTop,
        window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
        timer = {
          step: 60,
          times: 16,
          FLOOR_OFFSETTOP: floor_offsetTop,
        }
      if (window_scrollTop > floor_offsetTop) {
        this.setFloorScrollArrowUp(timer)
      } else if (window_scrollTop == floor_offsetTop) {
        return false
      } else {
        this.setFloorScrollArrowDown(timer)
      }
    },
    /**
     * 設置樓層向上滾動
     * @param {Object} timer 定時器配置
     */
    setFloorScrollArrowUp (timer) {
      clearInterval(this.timer)
      this.timer = setInterval(() => {
        let window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        if (window_scrollTop <= timer.FLOOR_OFFSETTOP) {
          document.documentElement.scrollTop = timer.FLOOR_OFFSETTOP
          document.body.scrollTop = timer.FLOOR_OFFSETTOP
          clearInterval(this.timer)
        } else {
          document.documentElement.scrollTop = window_scrollTop - timer.step
          document.body.scrollTop = window_scrollTop - timer.step
        }
      }, timer.times)
    },
    /**
     * 設置樓層向下滾動
     * @param {Object} timer 定時器配置
     */
    setFloorScrollArrowDown (timer) {
      clearInterval(this.timer)
      this.timer = setInterval(() => {
        let window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        if (window_scrollTop >= timer.FLOOR_OFFSETTOP) {
          document.documentElement.scrollTop = timer.FLOOR_OFFSETTOP
          document.body.scrollTop = timer.FLOOR_OFFSETTOP
          clearInterval(this.timer)
        } else {
          document.documentElement.scrollTop = window_scrollTop + timer.step
          document.body.scrollTop = window_scrollTop - timer.step
        }
      }, timer.times)
    },
    /**
     * 監聽窗口滾動樓層導航動態定位
     */
    floorSrcollEventListener () {
      const { nav_item, floor_item } = this.element
      const window_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
      for (let i = 0, len = floor_item.length; i < len; i++) {
        let floor_offsetTop = floor_item[i].offsetTop - floor_item[0].offsetTop
        if (window_scrollTop >= floor_offsetTop) {
          for (let n = 0, len = nav_item.length; n < len; n++) {
            const current_classList = nav_item[n].classList
            i === n
              ? current_classList.add('active')
              : current_classList.remove('active')
          }
        }
      }
    }
  }
}
</script>

<style scoped>
.floor-warpper {
  width: 1000px;
  margin: auto;
}
.floor-nav {
  position: fixed;
  top: 200px;
  left: 50px;
}
.nav-list {
  width: 48px;
  padding: 0;
  display: inline-block;
  text-align: center;
  background-color: #f8f8f8;
}
.nav-list-item {
  display: inline-block;
  width: 100%;
  height: 100%;
  line-height: 48px;
  vertical-align: middle;
  align-self: center;
  border-bottom: 1px solid #fff;
  cursor: pointer;
}
.nav-list-item.active,
.nav-list-item:hover {
  color: #FFF;
  background-color: #404040;
}

.floor-item {
  width: 100%;
  margin: 60px auto;
  min-height: 300px;
  text-align: center;
  color: #FFF;
  background-color: #404040;
}
</style>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章