动态楼层导航

目录

动态楼层导航

页面布局

数据模型

滚动事件监听

监听窗口滚动楼层导航动态定位

设置楼层导航事件驱动方法

设置楼层向上滚动

设置楼层向下滚动

完整代码


在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>

 

Logo

前往低代码交流专区

更多推荐