今天分享前端開發學習中的一個很經典的案例——原生JS實現無縫輪播圖。css
需求:前端
1.鼠標移入輪播圖時左右兩邊顯示上一頁下一頁按鈕,移出時隱藏數組
2.鼠標點擊箭頭,圖片發生輪播函數
3.點擊號碼,切換到指定圖片學習
4.鼠標移出,圖片每隔必定時間自動輪播動畫
5.當圖片輪播到最後或最前一張的時候,圖片無縫循環切換this
HTML頁面結構:這裏把圖片換成背景顏色了,使用時直接添加圖片路徑便可spa
1 <div class="all" id='box'> 2 <div class="screen"> 3 <ul> 4 <li><img src="" width="500" height="200" style="background-color: yellowgreen;"/></li> 5 <li><img src="" width="500" height="200" style="background-color: pink;"/></li> 6 <li><img src="" width="500" height="200" style="background-color: skyblue;"/></li> 7 <li><img src="" width="500" height="200" style="background-color: greenyellow;"/></li> 8 <li><img src="" width="500" height="200" style="background-color: plum;"/></li> 9 <li><img src="" width="500" height="200" style="background-color: orange;"/></li> 10 </ul> 11 <ol> 12 <li class="current">1</li> 13 <li>2</li> 14 <li>3</li> 15 <li>4</li> 16 <li>5</li> 17 </ol> 18 19 </div> 20 <div id="arr"><span id="left"><</span><span id="right">></span></div> 21 </div>
CSS樣式:樣式部分比較簡單,重點讓li標籤浮動並排,而後在盒子(類名爲screen的div)裏顯示其中一張,其餘的隱藏(overflow:hidden),整個輪播思想就是移動整個ul標籤。code
1 <style type="text/css"> 2 * { 3 padding: 0; 4 margin: 0; 5 list-style: none; 6 border: 0; 7 } 8 9 .all { 10 width: 500px; 11 height: 200px; 12 padding: 7px; 13 border: 1px solid #ccc; 14 margin: 100px auto; 15 position: relative; 16 } 17 18 .screen { 19 width: 500px; 20 height: 200px; 21 overflow: hidden; 22 position: relative; 23 } 24 25 .screen li { 26 width: 500px; 27 height: 200px; 28 overflow: hidden; 29 float: left; 30 } 31 32 .screen ul { 33 position: absolute; 34 left: 0; 35 top: 0px; 36 width: 3000px; 37 } 38 39 .all ol { 40 position: absolute; 41 right: 10px; 42 bottom: 10px; 43 line-height: 20px; 44 text-align: center; 45 } 46 47 .all ol li { 48 float: left; 49 width: 20px; 50 height: 20px; 51 background: #fff; 52 border: 1px solid #ccc; 53 margin-left: 10px; 54 cursor: pointer; 55 } 56 57 .all ol li.current { 58 background: yellow; 59 } 60 61 #arr { 62 display: none; 63 } 64 65 #arr span { 66 width: 40px; 67 height: 40px; 68 position: absolute; 69 left: 5px; 70 top: 50%; 71 margin-top: -20px; 72 background: #000; 73 cursor: pointer; 74 line-height: 40px; 75 text-align: center; 76 font-weight: bold; 77 font-family: '黑體'; 78 font-size: 30px; 79 color: #fff; 80 opacity: 0.3; 81 border: 1px solid #fff; 82 } 83 84 #arr #right { 85 right: 5px; 86 left: auto; 87 } 88 </style>
JS處理:blog
第一步:完成輪播圖事件的添加 :用一個全局變量index記錄當前須要展現的圖片的索引
(1)鼠標移入移出事件:鼠標移入,顯示左右切換按鈕,移出時隱藏
(2)上一頁下一頁按鈕點擊事件點擊下一頁:index++,點擊上一頁:index--
(3)頁碼點擊事件:切換指定圖片
第二步:完成上一頁和下一頁
(1)點擊移動以前給ul添加邊界檢測:不然點擊下一頁會無限往右滾動
(2)修改當前索引(自增/自減),索引表示的是當前ul應該展現第幾張圖片
(3)移動ul(目標距離 = -index * screen的寬度)
(4)頁碼保持同步(當前顯示的是第幾張圖片,下方頁碼對應索引高亮)
第三步:完成無限輪播 核心思想:n+1
(1)常規思路:圖片滾動時,當滾動到最後一張時,咱們偷偷的快速改變ul的位置到第一張(不要動畫,瞬間改變)
ul.style.left = '0px'; //ul回到初始位置
index = 0; //index恢復到0
(2)問題發現:這種方式能夠實現無限輪播,可是在下一輪無限的時候第一張會被跳過去
緣由:咱們手動改變了index爲0,而動畫又須要index+1,因此會錯過index爲0的那一張
(3)解決方案:咱們在最後一張圖片的後面加上第一張圖片(第6張)可讓用戶看到滾動效果,而後滾動到第六張時,再改變ul回到初始位置
好處:①用戶能夠看到滾動效果,不影響體驗; ②恰好第6張與第一張是同一張圖片,快速改變位置不會形成動畫的閃現
(4)當圖片index爲最後一張的的時候,頁碼應該顯示第一個,由於最後一張和第一張是同一張圖片
第四步:完成點擊頁碼跳轉
(1)點擊的是第幾個頁碼,移動動畫的目標距離 = -index * screen.offsetWidth
(2)排他思想改變頁碼樣式
(3)頁碼的下標須要與圖片下標index保持一致,不然會產生衝突,即點擊頁碼的時候,要讓圖片下標index與頁碼下標一致
第五步:自動無限輪播
至關於每隔一段時間自動點擊下一頁按鈕,代碼邏輯徹底不變
(1)將輪播代碼封裝成一個函數
(2)開啓定時器,每隔一段時間執行這個函數
(3)鼠標移入時清除定時器,移出時開啓定時器
1 <script> 2 // 1.獲取頁面對應的元素 3 var box=document.getElementById("box"); //最外部大盒子 4 var arr=document.getElementById("arr"); 5 var screen=document.getElementsByClassName("screen")[0]; //輪播圖顯示區域div 6 var ul=document.getElementsByTagName("ul")[0]; //顯示圖片的ul 7 var ol=document.getElementsByTagName("ol")[0]; //顯示頁碼的ol 8 var left=document.getElementById("left"); //上一張箭頭 9 var right=document.getElementById("right"); //下一張箭頭 10 var index=0; ////聲明一個變量記錄圖片的索引,默認第0張圖片 11 12 //2.給box添加鼠標移入和移出事件 13 //2.1 鼠標移入 14 box.onmouseover= function () { 15 arr.style.display="block"; //顯示上一頁下一頁箭頭 16 clearInterval(timeId); //清除定時器(即鼠標移入時,圖片要中止自動輪播) 17 }; 18 //2.2 鼠標移出 19 box.onmouseout= function () { 20 arr.style.display="none"; //隱藏箭頭 21 timeId=setInterval(scroll,2000); //重啓定時器(鼠標移出,圖片要恢復自動輪播) 22 }; 23 24 //3.給上一頁下一頁箭頭添加點擊事件 25 //3.1 下一頁,圖片向左輪播 26 right.onclick= function () { 27 scroll(); 28 }; 29 //3.2 上一頁,圖片向右輪播 30 left.onclick= function () { 31 //(1)邊界檢測,若是當前已是第一張,則不作任何處理 32 if(index==0){ 33 //無限輪播原理:若是當前是第一張,則偷偷修改ul的位置是最後一張(第一張與最後一張是同一張圖片) 34 index=ul.children.length-1; //index恢復到最後一張 35 ul.style.left=-index*screen.offsetWidth+"px"; ////ul回到最後一張位置 36 } 37 //(2)索引自減 38 index--; 39 // (3)向左移動ul:目標距離 = -screen的寬度 * 索引 40 animationMove(ul,-index*screen.offsetWidth,10); 41 indexShow(); //同步頁碼樣式 42 }; 43 44 //4.給頁碼添加點擊事件 45 for(var i=0;i<ol.children.length;i++){ 46 //4.1 循環遍歷數組時給每個頁碼添加一個liIndex屬性記錄下標 47 ol.children[i].liIndex=i; 48 ol.children[i].onclick= function () { 49 index=this.liIndex-1; 50 scroll(); 51 }; 52 } 53 54 var timeId=setInterval(scroll,2000); 55 // 封裝一個向右輪播的函數 56 function scroll(){ 57 //(1)邊界檢測:若是當前已是最後一張(第n+1張,n表明須要輪播的圖片數量) 58 if(index==ul.children.length-1){ 59 //無限輪播的原理就是滾動到最後一張的時候,偷偷快速的改變ul的位置到第一張(不要任何動畫,一瞬間改變) 60 index=0; //index恢復到0 61 ul.style.left=0+"px"; //ul回到初始位置 62 } 63 // (2)索引自增 64 index++; 65 // (3)向右移動ul:目標距離 = -screen的寬度 * 索引 66 animationMove(ul,-index*screen.offsetWidth,10); 67 indexShow(); //同步頁碼樣式 68 } 69 //5.頁碼樣式保持同步:排他思想(當前頁碼添加樣式,其餘頁碼移除該樣式) 70 function indexShow(){ 71 for(var i=0;i<ol.children.length;i++){ 72 if(i==index){ 73 ol.children[i].classList.add("current"); 74 }else{ 75 ol.children[i].classList.remove("current"); 76 } 77 //特殊狀況:當index爲最後一張的時候,頁碼應該顯示第一張 78 if(index==ul.children.length-1){ 79 ol.children[0].classList.add("current"); 80 } 81 } 82 } 83 // 封裝一個滾動動畫函數 84 function animationMove(obj,target,speed){ 85 clearInterval(obj.timeId); //每次執行動畫先清除原有的定時器 86 obj.timeId=setInterval(function () { 87 var currentLeft=obj.offsetLeft; //獲取當前位置 88 var isLeft=currentLeft>target?true:false; //是否往左走 89 if(isLeft){ 90 currentLeft-=10; //往左走 91 }else{ 92 currentLeft+=10; //往右走 93 } 94 if(isLeft?currentLeft>target:currentLeft<target){ 95 obj.style.left=currentLeft+"px"; //若是當前位置不是在目標位置則進行位置處理 96 }else{ 97 clearInterval(obj.timeId); 98 obj.style.left=target+"px"; 99 } 100 // if(currentLeft>target){ 101 // currentLeft-=10; 102 // obj.style.left=currentLeft+"px"; 103 // }else if(currentLeft<target){ 104 // currentLeft+=10; 105 // obj.style.left=currentLeft+"px"; 106 // }else{ 107 // clearInterval(obj.timeId); 108 // obj.style.left=target+"px"; 109 // } 110 },speed); 111 } 112 </script>