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>