使用原生JS且稳定无bug的轮播图

20190313,花了整个白天跟着慕课网的教程做了这个轮播图,受益颇多。老师讲的切图过程中不响应点击事件那里有点bug,已经修正。

5张图片放在img文件夹中,分别取名timg1.jpg, timg2.jpg……timg5.jpg。图片分辨率均为600*400

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>Slider</title>
  6     <style>
  7         * {
  8             padding: 0;
  9             margin: 0;
 10             -webkit-box-sizing: border-box;
 11           -moz-box-sizing: border-box;
 12             box-sizing: border-box;
 13         }
 14         #container {
 15             position: relative;
 16             height: 400px;
 17             width: 600px;
 18             margin: 100px auto;
 19             overflow: hidden;
 20         }
 21         /* 怎么让7张图片排成一排呢?将7张图片的父容器宽度设为600*7,img再float */
 22         /* 值得注意的一点是,这个图片框必须position为absolute,这样才能让JS通过修改该元素的left值来定位 */
 23         #pics {
 24             position: absolute;
 25             width: 4200px;
 26             height: 100%;
 27             z-index: 1;
 28         }
 29         /* 为什么img不float时,就排不下?img之间的间距是哪来的呢?不是reset了吗? */
 30         #pics>img {
 31             float: left;
 32         }
 33         #dots {
 34             position: absolute;
 35             height: 10px;
 36             width: 300px;
 37             left: 150px;
 38             bottom: 10px;
 39             z-index: 2;
 40         }
 41         /* 这里比较陌生,需要注意 */
 42         #dots>span {
 43             cursor: pointer;
 44             float: left;
 45             height: 6px;
 46             width: 50px;
 47             margin: 2px 5px;
 48             background: rgb(253, 253, 253);
 49             border-radius: 2px;
 50             box-shadow: 0px 1px 2px rgb(223, 223, 223);
 51         }
 52         #dots .on {
 53             background: orange;
 54         }
 55         /* 这里将a标签当块级元素处理 */
 56         .arrow {
 57             position: absolute;
 58             cursor: pointer;
 59             text-decoration: none; 
 60             display: none;
 61             height: 40px;
 62             width: 30px;
 63             line-height: 40px;
 64             font-size: 20px;
 65             font-weight: 500;
 66             color: rgb(235, 235, 235);
 67             /* text-align: center; */
 68             background: rgba(90, 90, 90, 0.4);
 69             z-index: 2;
 70         }
 71         #prev {
 72             left: 0;
 73             top: 165px;            
 74             padding-left: 5px;
 75             border-top-right-radius: 20px;
 76             border-bottom-right-radius: 20px;
 77         }
 78         #next {
 79             right: 0;
 80             top: 165px;    
 81             padding-left: 10px;
 82             border-top-left-radius: 20px;
 83             border-bottom-left-radius: 20px;
 84         }
 85         #container:hover .arrow{display: block;}
 86         .arrow:hover {background: rgba(82, 82, 82, 0.5)}
 87     </style>
 88 
 89 </head>
 90 <body>    
 91     <div id="container">
 92         <!-- 这里为什么默认pics容器的绝对定位的left为-600呢?因为第一张图是timg5 -->
 93         <div id="pics" style="left: -600px;">
 94             <img src="img/timg5.jpg" alt="1">
 95             <img src="img/timg1.jpg" alt="1">
 96             <img src="img/timg2.jpg" alt="2">
 97             <img src="img/timg3.jpg" alt="3">
 98             <img src="img/timg4.jpg" alt="4">
 99             <img src="img/timg5.jpg" alt="5">
100             <img src="img/timg1.jpg" alt="5">
101         </div>
102 
103         <div id="dots">
104             <!-- 注意这里的index="x"是一个自定义属性 -->
105             <span index="1" class="on"></span>
106             <span index="2"></span>
107             <span index="3"></span>
108             <span index="4"></span>
109             <span index="5"></span>
110         </div>
111 
112         <a href="javascript:;" id="prev" class="arrow">&lt</a>
113         <a href="javascript:;" id="next" class="arrow">&gt</a>
114     </div>
115 
116     <script>
117         window.onload = function() {
118             var container = document.getElementById('container');
119             var pics = document.getElementById('pics');
120             var buttons = document.getElementById('dots').getElementsByTagName('span');
121             var prev = document.getElementById('prev');
122             var next = document.getElementById('next');
123             var index = 1;
124             var isMoving = false;//是否在切换运动中
125             var timer; //最后实现自动播放时用的
126 
127             //获取完元素就开始基础的事件绑定,先实现点击左右箭头切换
128             //最开始分别写左右按钮
129             //值得注意的是onclick和addEventListener的用法,比如xx.onclick=animate(-/+600)是无效的!必须套在匿名函数中。但是若animate函数不用传参,则可以不套。
130             //下面五个条的亮暗和左右点击操作有关,于是showButton函数要在左右按钮的onclick事件里面执行
131             prev.onclick = function() {
132                 if(!isMoving){
133                     if(index == 1) {
134                         index = 5;
135                     } else {
136                         index--;
137                     }                
138                 showButton();                                
139                 animate(600);
140                 }                        
141             }
142             next.onclick = function() {
143                 if(!isMoving) {
144                     if(index == 5) {
145                         index = 1;
146                     } else {
147                         index++;
148                     }                    
149                         
150                     showButton();                    
151                     animate(-600);    
152                 }    
153             }
154 
155             function animate(offset) {
156                 // var isMoving = true; 这样写就没用啦!因为这样没改变外面的isMoving值,那些click事件一直获取到外部的isMoving==false,所以运动时还是会响应
157                 isMoving = true;
158                 var newLeft = parseInt(pics.style.left) + offset;
159                 //下面三个变量的定义和go函数的if语句是来实现平移动画的。
160                 var time = 300; //位移总的时间
161                 var interval = 10; //位移间隔时间
162                 var speed = offset/(time/interval); //每次的位移量
163 
164                //当快速地点击切换图片时,会进行大量的计算,还在运动过程中就又要响应,这是既不合理又折磨浏览器的。
           //所以应该设定运动过程中不响应切换图片的操作。设一个参数表示是否在运动的状态,参数放在哪呢?当然不是放在这里啦。
           //运动状态是一个宏观的大家都能得到的,并且那些外部的点击事件也要参考这个状态来决定是否执行。这里是用来“制造运动”的。
           //所以一执行这个animate函数 就开始运动了,执行到else里面就运动结束。 接下来就是通过这个isMoving状态来控制那些点击事件了。
165 166 //记住左移时 offset为正,speed为正。越左边pics.style.left越大。 167 function go() { 168 if ( (speed < 0 && parseInt(pics.style.left) > newLeft) || (speed > 0 && parseInt(pics.style.left) < newLeft) ) { 169 pics.style.left = parseInt(pics.style.left) + speed + 'px'; 170 setTimeout(go, interval);//递归 171 } 172 else { 173 isMoving = false; 174 //下面这些是第一步骤。 175 pics.style.left = newLeft + 'px'; 176 //到这里要实现无限滚动,发现需要多次用到pics.style.left值,便存到newLeft 177 if(newLeft > -600) { 178 pics.style.left = -3000 + 'px'; 179 } 180 if(newLeft < -3000) { 181 pics.style.left = -600 + 'px'; 182 } 183 } 184 } 185 go(); //不调用就不会执行哦 186 } 187 188 //注意亮起对应的小长条之前要把那个亮着的长条给灭掉 189 //还有很重要的一点,如果点右箭头使得index到5了,而buttons[5]不存在,控制台报错,左箭头使index减到-1也是如此。
         //因此要在左右箭头的点击函数里改进。为什么到那里而不在showbutton函数里呢?因为showButton并没有控制index的加减。
190 function showButton() { 191 for(var i = 0; i < buttons.length; i++) { 192 if(buttons[i].className == 'on') { 193 buttons[i].className = ''; 194 break; 195 } 196 } 197 buttons[index-1].className = 'on'; 198 } 199 200 //接下来实现点击下面5个长条(button)来跳转到对应的图片,像左右箭头一样调用animate函数,不同的是左右箭头知道offset为±600,
         //这里则要算出跳了多少个点再乘-600px。这里很巧妙,利用span里面自定义的属性index和现在程序里表示当前哪个class为on的button的index值来做比较。
         //前者是目标元素,后者是亮的元素。
201 for(var i = 0; i < buttons.length; i++) { 202 buttons[i].onclick = function() { 203 //下面这一句是用来判断当前的button是不是已经亮了,如果是的话就什么都不干,没必要进行接下去的那些计算。这是一个小优化点。 204 if(!isMoving) { 205 if(this.className == 'on') { return; } 206 var myIndex = parseInt(this.getAttribute('index')); 207 var offset = -600 * (myIndex - index); 208 209 animate(offset); 210 211 //注意下面别忘了 212 index = myIndex; 213 showButton(); 214 } 215 216 } 217 } 218 219 //接下来就是加上切换时的移动动画。在哪加呢?在掌控left值的animate函数里面。 220 221 //最后是自动轮播的功能 222 function play() { 223 timer = setInterval(function() { 224 next.onclick(); 225 }, 2000); 226 } 227 228 function stop() { 229 clearInterval(timer); 230 } 231 232 container.onmouseover = stop; 233 container.onmouseout = play; 234 235 play(); 236 } 237 </script> 238 </body> 239 </html>

猜你喜欢

转载自www.cnblogs.com/garmin6/p/10525537.html
今日推荐