为什么使用onmousewheel而不是onscroll?
- onmousewheel事件在没有滚动条的时候也能触发,而onscroll需要有滚动条才能触发,且onscroll多与scrollTop一起使用
CSS:子节点使用了绝对定位absolute,改变其top来显示所需要的页面,通过transition来展示变化的过渡效果
JS: 使用onmousewheel事件(火狐浏览器也做了相应兼容),来判断滚轮是向上还是向下滚动,由此改变index(子节点索引)的top值
1)通过父元素外面在套一个div,设置overflow:hidden来截取可视内容,然后控制父元素的marginTop来显示效果(推荐)
优点:利于别的信息的展示,不会使该元素内容架空在整个页面的内容之外
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
html, body {
height: 100%;
}
* {
margin: 0;
padding: 0;
}
li {
height: 100vh;
}
.wrapper-box {
height: 100vh;
overflow: hidden;
}
.wrapper {
width: 100%;
transition: all .5s;
}
ul > li {
height: 100vh;
width: 100%;
}
ul > li:nth-child(1) {
background: red;
}
ul > li:nth-child(2) {
background: blue;
}
ul > li:nth-child(3) {
background: green;
}
ul > li:nth-child(4) {
background: gold;
}
.dot {
position: fixed;
right: 50px;
top: 50%;
}
.dd-dot {
border-radius: 50%;
width: 20px;
height: 20px;
background:#fff;
margin-bottom: 10px;
}
</style>
<body>
<dl class="dot">
<dd class="dd-dot"></dd>
<dd class="dd-dot"></dd>
<dd class="dd-dot"></dd>
<dd class="dd-dot"></dd>
</dl>
<div class="wrapper-box">
<ul class="wrapper">
<li class="li-page"></li>
<li class="li-page"></li>
<li class="li-page"></li>
<li class="li-page"></li>
</ul>
</div>
</body>
<script>
let box = document.getElementsByClassName('wrapper')[0]
let liChild = box.children
let liDot = document.getElementsByClassName('dd-dot')
let childLength = liChild.length;
let index = 0,
timer,
Delta,
e,
flag = true;
const BOX_CHANGE_TIME = 1000 //页面动画的过渡时间
if (window.addEventListener) //FF,火狐浏览器会识别该方法
window.addEventListener('DOMMouseScroll', slideEvent, false);
window.onmousewheel = function (event) {
if (flag) { // 防止多次滚轮滚动多个页面,保证在上个页面动画结束后,发生下一个页面
flag = false;
slideEvent(event);
setTimeout(function () {
flag = true;
}, BOX_CHANGE_TIME)
}
}
for (let i = 0; i < liDot.length; i++) {
liDot[i].addEventListener('click', function () {
index = i - 1
slideEvent(event)
})
}
function slideEvent(event) {
clearTimeout(timer); //不会一次滚动触发多次事件
timer = setTimeout(function () {
e = event || window.event;
// IE、chrome监听的是wheelDelta,向下滚动其值为-120;向上滚动其值为120
if (e.wheelDelta) {
Delta = e.wheelDelta / 120;
//火狐浏览器监听的是detail,向下滚动其值为3;向上滚动其值为-3
} else if (e.detail) {
Delta = -e.detail / 3; //取负数,以保证符号相同
}
if (Delta > 0) { //向上
index = (index === 0 ? 0 : --index);
} else { //向下
index = (index === childLength - 1 ? childLength - 1 : ++index);
if (index > 3) {
index = 3;
}
}
box.style.marginTop = -index * 100 + "vh";
}, 100);
}
</script>
</html>
2)设置父元素为fixed,子元素为absolute,控制子元素的top,来显示效果
优点:对于一些响应式,且不需要展示别的内容,只有滑动模块展示的内容,可以更好的控制
缺点:需要通过css初始化每个子元素的top值,不易于别的信息的展示,如导航栏等
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
* {
padding: 0;
margin: 0;
}
li {
list-style: none;
}
.dot {
position: fixed;
z-index: 1000;
width: 40px;
height: 200px;
right: 30px;
top: 50%;
}
.dot ul li {
width: 16px;
height: 16px;
border-radius: 50%;
background: rgb(132, 132, 173);
margin: 20px auto;
position: relative;
cursor: pointer;
}
.dot ul li .liBg {
position: absolute;
border-radius: 50%;
top: -4px;
left: -4px;
width: 24px;
height: 24px;
transition: all 1s;
z-index: 200;
background: rgba(134, 134, 201, 0.555);
display: none;
}
#box {
position: fixed;
width: 100%;
height: 100%;
}
.box1,
.box2,
.box3,
.box4 {
width: 100%;
height: 100%;
position: absolute;
left: 0;
transition: all 1s;
text-align: center;
}
.box1 {
background: #114b5f;
top: 0;
}
.box2 {
background: #028090;
top: 100%;
}
.box3 {
background: #e4fde1;
top: 200%;
}
.box4 {
background: #456990;
top: 300%;
}
</style>
<body>
<div class="dot">
<ul>
<li>
<div class="liBg"></div>
</li>
<li>
<div class="liBg"></div>
</li>
<li>
<div class="liBg"></div>
</li>
<li>
<div class="liBg"></div>
</li>
</ul>
</div>
<div id="box">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
</div>
</body>
<script>
let box = document.getElementById('box'),
boxChild = box.children, //获取子节点
libg = document.getElementsByClassName('liBg')
libg[0].style.display = 'block'
let list = document.querySelectorAll('.dot li')
let childLength = boxChild.length;
let index = 0,
timer,
Delta,
e,
flag = true;
const BOX_CHANGE_TIME = 1000; //页面动画的过渡时间
if (window.addEventListener) //FF,火狐浏览器会识别该方法
window.addEventListener('DOMMouseScroll', slideEvent, false);
window.onmousewheel = function (event) {
if (flag) { // 防止多次滚轮滚动多个页面,保证在上个页面动画结束后,发生下一个页面
flag = false;
slideEvent(event);
setTimeout(function () {
flag = true;
}, BOX_CHANGE_TIME)
}
}
for (let i = 0; i < list.length; i++) {
list[i].addEventListener('click', function () {
index = i - 1
slideEvent(event)
})
}
function slideEvent(event) {
clearTimeout(timer); //不会一次滚动触发多次事件
timer = setTimeout(function () {
e = event || window.event;
// IE、chrome监听的是wheelDelta,向下滚动其值为-120;向上滚动其值为120
if (e.wheelDelta) {
Delta = e.wheelDelta / 120;
//火狐浏览器监听的是detail,向下滚动其值为3;向上滚动其值为-3
} else if (e.detail) {
Delta = -e.detail / 3; //取负数,以保证符号相同
}
if (Delta > 0) { //向上
index = (index === 0 ? 0 : --index);
} else { //向下
index = (index === childLength - 1 ? childLength - 1 : ++index);
if (index > 3) {
index = 3;
}
}
for (let i = 0; i < childLength; i++) {
boxChild[i].style.top = (i - index) * 100 + "%";
}
for (let i = 0; i < libg.length; i++) {
libg[i].style.display = 'none';
}
libg[index].style.display = 'block'
}, 100);
}
</script>
</html>
成果图: