1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8">
6 <title>index</title>
7 </head>
8 <style>
9 * {
10 margin: 0;
11 padding: 0;
12 }
13
14 div {
15 width: 100%;
16 height: 100%;
17 }
18
19 .one {
20 background-color: #1bbc9b;
21 }
22
23 .sec {
24 background-color: #4bbfc3;
25 }
26
27 .thr {
28 background-color: #7baabe;
29 }
30 </style>
31
32 <body>
33 <div class="full one">1</div>
34 <div class="full sec">2</div>
35 <div class="full thr">3</div>
36 </body>
37 <script>
38 //添加滚动监听
39 document.addEventListener('mousewheel', wheel, false);
40
41 //判断一次滚动是是否完成
42 var isComplete = true;
43 //隐藏滚动条
44 document.body.style.overflow = 'hidden';
45
46 //获取滚动的元素
47 var fullList = document.getElementsByClassName("full");
48
49 //因为是类数组对象,不是数组对象,所以只能使用call的方式来调用
50 Array.prototype.forEach.call(fullList, function(value) {
51 //获取一个网页满屏的高
52 value.style.height = window.innerHeight + 'px';
53 })
54
55 //如果窗口大小改变执行的函数
56 window.onresize = function() {
57 Array.prototype.forEach.call(fullList, function(value) {
58 value.style.height = window.innerHeight + 'px';
59 });
60
61 //改变窗口大小后,应该仍是一个元素占满全屏
62 if(document.body.scrollTop % window.innerHeight) {
63 isComplete = false;
64 //根据四舍五入判断滚动位置
65 let tmp = Math.round(document.body.scrollTop / window.innerHeight) * window.innerHeight;
66
67 //使用运动框架
68 showAnimate(document.body, { 'scrollTop': tmp }, function() {
69 isComplete = true;
70 });
71 }
72 };
73
74 //滚动函数
75 function wheel(e) {
76 //等待上一个滚动完成
77 if(isComplete) {
78
79 //滚动进行时
80 isComplete = false;
81
82 //判断是往上滚动还是往下滚动
83 if(e.wheelDelta < 0) {
84 //要滚动到的点
85 let arrivePoint = document.body.scrollTop + window.innerHeight;
86
87 //最大的滚动点
88 let maxBottom = document.body.offsetHeight - window.innerHeight;
89
90 //如果超出了最大的滚动点,则赋值为最大滚动点
91 arrivePoint = arrivePoint > maxBottom ? maxBottom : arrivePoint;
92
93 showAnimate(document.body, { 'scrollTop': arrivePoint }, function() {
94 isComplete = true;
95 });
96 } else {
97 let arrivePoint = document.body.scrollTop - window.innerHeight;
98
99 //最小滚动点为0
100 arrivePoint = arrivePoint < 0 ? 0 : arrivePoint;
101 showAnimate(document.body, { 'scrollTop': arrivePoint }, function() {
102 isComplete = true;
103 });
104 }
105 }
106 }
107 /**
108 *函数作用:执行动画
109 *接受参数:obj(需要运动的DOM元素)
110 * json(需要改变的属性集合,json格式)
111 * fn(回调函数)
112 */
113 function showAnimate(obj, json, fn) {
114 clearInterval(obj.timer);
115 //表示运动是否都已经停止
116 var flag = true;
117 obj.timer = setInterval(function() {
118 //循环json
119 for(var i in json) {
120 if(i == 'opacity') {
121 //获取透明度值,round四舍五入去除小数点
122 var icur = Math.round(parseFloat(getStyle(obj, i)) * 100);
123 } else {
124 //获取属性值
125 var icur = parseInt(getStyle(obj, i)) || obj[i];
126 }
127 //缓冲运动,speed随时变换
128 var speed = (json[i] - icur) / 10;
129 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //速度向上或者下取整,防止到不了over位置
130 //如果有一个没到达终点就是false
131 if(json[i] !== icur) {
132 flag = false;
133 } else {
134 flag = true;
135 }
136 if(i == 'opacity') {
137 obj.style.filter = 'alpha(opacity:' + (icur + speed) + ')'; //IE兼容
138 obj.style.opacity = (icur + speed) / 100;
139 } else if(obj[i] || obj[i] == 0) {
140 obj[i] = icur + speed;
141 } else {
142 obj.style[i] = icur + speed + 'px';
143 }
144 // console.log(icur + ' ' + json[i]);
145 }
146 //检查是否所有的运动都已经停止
147 if(flag) {
148 clearInterval(obj.timer);
149 if(fn) {
150 fn();
151 }
152 }
153 }, 13);
154 }
155 /**
156 *函数作用:返回样式属性值
157 *接受参数:obj(需要获取属性的DOM元素)
158 * attr(需要获取的属性名称)
159 */
160 function getStyle(obj, attr) {
161 if(obj.currentStyle) {
162 return obj.currentStyle[attr]; //IE兼容
163 } else {
164 return getComputedStyle(obj, false)[attr];
165 }
166 }
167 </script>
168
169 </html>