<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./js/jquery.js"></script>
<style>
body,
html,
wrap_con {
scroll-behavior: smooth;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.w {
width: 1280px;
margin: 0 auto;
}
header {
height: 100px;
background-color: #30f3f4;
}
nav {
margin: 20px 0;
height: 100px;
background-color: #ff3040;
}
.wrap_con {
width: 100%;
height: 100%;
}
.wrap_con>div {
width: 100%;
height: 500px;
margin-bottom: 20px;
font-size: 30px;
text-align: center;
font-weight: 700;
line-height: 500px;
color: #fff;
}
.con1 {
background-color: #333;
}
.con2 {
background-color: #555;
}
.con3 {
background-color: #777;
}
.con4 {
background-color: #999;
}
.con5 {
background-color: #aaa;
}
footer {
height: 500px;
background-color: #3040ff;
}
.slide_nav {
display: none;
position: fixed;
top: 50%;
transform: translateY(-50%);
left: 0;
width: 100px;
}
.slide_nav span {
float: left;
width: 80%;
height: 30px;
line-height: 30px;
text-align: center;
cursor: pointer;
}
.active {
background-color: #ff3040;
color: #fff;
}
</style>
<script>
$(function () {
// 3. 定义节流阀,控制一个页面同时只能由一个动画在进行
let flag = true // true 表示有动画正在进行
// 1. 当页面滚动到 nav 区域, 让侧边栏显示出来
$(window).scroll(function () {
// 1.1 获取 nav 区域离上边的距离
let top = $('nav').offset().top
// console.log(top);
// 1.2 当页面滚动到 nav 区域,显示侧边栏
// if ($('html,body').scrollTop() >= top) {
// $('.slide_nav').show()
// } else {
// $('.slide_nav').hide()
// }
// 1.2 三元表达式
$('html,body').scrollTop() >= top ? $('.slide_nav').show() : $('.slide_nav').hide()
// 4. 当页面滚动到对应区域的时候,让对应的 span 高亮
$('.wrap_con>div').each(function (i, item) {
// 如果有动画正在进行,return
if (flag == false) return
// 4.1 首先获取到每个电梯层离页面顶部的距离
let floorTop = $(item).offset().top
// 4.2 当页面滚动到对应区域,让对应的 span 高亮
if ($(window).scrollTop() >= floorTop - 1) { // - 1 是因为浏览器计算式会丢失精度,可能高亮的不准确
$('.slide_nav span').eq(i).addClass('active').siblings().removeClass('active')
}
})
})
/*
// 2. 给每个 span 注册点击事件
$('.slide_nav span').click(function() {
// console.log(this);
// 3.1 做动画之前先检查有没有动画在进行
if (flag == false) {
// 如果有,直接退出函数g
return false
}
// 3.2 并且关闭节流阀
flag = false
// 2.1 获取索引号
let index = $(this).index()
// 2.2 点击每个span 获取对应的内容区域的高度
let currentTop = $('.wrap_con>div').eq(index).offset().top
// console.log(currentTop);
// 2.3 给整个页面做动画,显示对应的区域
$('html,body').animate({
scrollTop: currentTop
}, function() {
// 3.3 动画完成之后通过回调函数打开节流阀
flag = true
})
// 2.4 通过添加类名来改变背景色
$(this).addClass('active').siblings().removeClass('active')
})*/
})
</script>
</head>
<body>
<!-- 版心 -->
<div class="w">
<!-- 头部 -->
<header>
header
</header>
<!-- 导航栏 -->
<nav>
nav
</nav>
<!-- 电梯层 -->
<div class="wrap">
<div class="wrap_con">
<div class="con1" id="con1">con1</div>
<div class="con2" id="con2">con2</div>
<div class="con3" id="con3">con3</div>
<div class="con4" id="con4">con4</div>
<div class="con5" id="con5">con5</div>
</div>
</div>
<!-- 底部 -->
<footer>
footer
</footer>
<!-- 电梯遥控器 -.- -->
<div class="slide_nav">
<span class="active"><a href="#con1">con1</a></span>
<span><a href="#con2">con2</a></span>
<span><a href="#con3">con3</a></span>
<span><a href="#con4">con4</a></span>
<span><a href="#con5">con5</a></span>
</div>
</div>
</body>
</html>
<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 + 500 >= 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>