動態樓層導航
目錄
在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>