---恢復內容開始---
實現原理
通過自定義的animate函數來改變元素的left值讓圖片呈現左右滾動的效果
HTML:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <link rel="stylesheet" type="text/css" href="StyleSheet.css"> 6 <title></title> 7 </head> 8 <body> 9 <div id="scroll" class="scroll"> 10 <div id="box" class="box"> 11 <ul id="ul" style="left:-950px;"> 12 <li><img src="images/top_banner_bw01.jpg" width="950" height="438"></li> 13 <li><img src="images/top_banner_bw02.jpg" width="950" height="438"></li> 14 <li><img src="images/top_banner_bw03.jpg" width="950" height="438"></li> 15 <li><img src="images/top_banner_bw04.jpg" width="950" height="438"></li> 16 <li><img src="images/top_banner_bw05.jpg" width="950" height="438"></li> 17 </ul> 18 <ol id="olnavi"></ol> 19 </div> 20 <div id="last"></div> 21 <div id="next"></div> 22 </div> 23 <script src="a.js"></script> 24 </body> 25 </html>
CSS:
1 body, div, p, 2 h1, h2, h3, h4, h5, h6, 3 dl, dt, dd, ul, ol, li, 4 table, caption, th, td, 5 form, fieldset, input, textarea, select, 6 pre, address, blockquote, 7 embed, object { 8 margin: 0px; 9 padding: 0px; 10 } 11 12 ul, ol { 13 list-style:none; 14 } 15 16 img { 17 vertical-align: top; 18 } 19 20 .scroll { 21 width: 950px; 22 height: 438px; 23 margin: auto; 24 overflow: hidden; 25 position: relative; 26 } 27 28 .box { 29 width: 950px; 30 height: 438px; 31 overflow: hidden; 32 position: relative; 33 } 34 35 .box ul{ 36 width: 700%; 37 position: absolute; 38 left: 0; 39 top: 0; 40 padding:0px; 41 margin:0px; 42 } 43 44 .box ul li{ 45 float: left; 46 } 47 48 .scroll ol { 49 position: absolute; 50 right: 365px; 51 bottom: 5px; 52 } 53 54 .scroll ol li { 55 float: left; 56 width: 20px; 57 height: 20px; 58 border-radius: 50%; 59 background: #000; 60 margin-left: 10px; 61 cursor: pointer; 62 opacity: 0.5; 63 } 64 65 .scroll ol li.current { 66 background-color: #000099; 67 opacity: 0.8; 68 } 69 70 #last { 71 position: absolute; 72 bottom: 179px; 73 width: 80px; 74 height: 80px; 75 cursor: pointer; 76 } 77 78 #next { 79 position: absolute; 80 bottom: 179px; 81 right: 0px; 82 width: 80px; 83 height: 80px; 84 cursor: pointer; 85 }
JavaScript:
1 //1.先獲取html中的元素 2 var scroll = document.getElementById("scroll"); 3 var ul = document.getElementById("ul"); 4 var ulLis = ul.children; 5 var liWidth = ul.children[0].offsetWidth; 6 //2.再此之前,我們要明白,小圓點並不是寫死的,它是根據ul li中的圖片張數來決定的 。 7 var ol = document.getElementById("olnavi"); 8 for (var i = 0; i < ulLis.length - 2; i++) { 9 var li = document.createElement("li"); 10 li.id = (i + 1); //id用於后面為li添加事件 11 ol.appendChild(li); 12 13 } 14 ol.children[0].className = "current" //將第一個小圓點設置為觸發狀態 15 //3.要實現無縫滾動 就需要多兩張圖片才行 ,即克隆第一張圖片,放到最后一張的后面,克隆最后一張,放到第一張的前面。 16 var num = ulLis.length - 1; 17 ul.appendChild(ul.children[0].cloneNode(true)); 18 ul.insertBefore(ul.children[num].cloneNode(true), ul.firstChild); 19 //4.接下來為左右箭頭添加事件,鼠標放到箭頭上會變色 20 var last = document.getElementById("last"); 21 last.style.background = "url(./img/left.png)"; 22 last.style.width = "64px"; 23 24 last.addEventListener("mouseenter", function () { 25 last.style.background = "url(./img/newleft.png)"; 26 }, false); 27 28 last.addEventListener("mouseleave", function () { 29 last.style.background = "url(./img/left.png)"; 30 }, false); 31 32 var next = document.getElementById("next"); 33 next.style.background = "url(./img/right.png)"; 34 next.style.width = "64px"; 35 36 next.addEventListener("mouseenter", function () { 37 next.style.background = "url(./img/newright.png)"; 38 }, false); 39 40 next.addEventListener("mouseleave", function () { 41 next.style.background = "url(./img/right.png)"; 42 }, false); 43 // 5.我們接着用js做動畫 動畫部分包括: 44 // ①.鼠標點擊第幾個小圓點,就要展示第幾張圖片,並且小圓點的顏色也發生變化. 45 // ②. 鼠標點擊左右箭頭,圖片向左右移動一張 46 // ③圖片自動輪播,(這需要一個定時器) 47 // ④.鼠標放在圖片上,圖片停止自動播放(這需要清除定時器) 48 // ⑤.鼠標離開圖片,圖片繼續自動輪播 (重新開始定時器) 49 // 這里我們封裝了一個animate()動畫函數 50 function animate(obj, target) { //obj為需要移動的元素,在本文中為ul,target為需要移動到的位置 51 var speed = obj.offsetLeft < target ? 10 : -10; //判斷速度向左還是向右 52 obj.timer = setInterval(function () { //計時器每隔一定時間移動一次 53 var result = target - obj.offsetLeft; //剩余需要移動的距離 54 obj.style.left = obj.offsetLeft + speed + "px"; //改變元素的left來實現移動 55 if (Math.abs(result) <= Math.abs(speed)) { //當需要移動的距離小於速度時 56 clearInterval(obj.timer); //清除計時器 57 obj.style.left = target + "px"; //直接移動到需要移動的位置 58 flag = true; //將flag置為true,使點擊事件能再次觸發 59 } 60 }, 1); 61 } 62 //6.接下來把動畫函數賦給左右箭頭 63 var flag = true; //用於判斷上一個事件是否執行完畢,如果沒有執行完畢禁止再次觸發事件 64 var index = 1; //是第幾個小圓點 65 var lastclick = function () { 66 if (flag) { 67 flag = false; //進入事件將flag置為false 68 console.log(flag); 69 if (index === 1) { //判斷是否為第一張 70 index = 6; 71 ul.style.left = "-5994px"; //當移動到第一張時,再向右移前會替換到最后一張后面的第一張,然后再向右移動。 72 animate(ul, ul.offsetLeft + liWidth); //動畫函數一次向有移動一個圖片長度的距離 73 } 74 else { 75 animate(ul, ul.offsetLeft + liWidth); 76 } 77 index -= 1; //移動小圓點計數器 78 btnShow(index); //給新的小圓點高亮,取消上一個小圓點的高亮 79 } 80 } 81 last.addEventListener("click", lastclick, false); //將函數賦給點擊事件 82 83 var nextclick = function () { //向左移與向右移類似 84 if (flag) { 85 flag = false; 86 if (index === 5) { 87 index = 0; 88 ul.style.left = "0px"; 89 animate(ul, ul.offsetLeft - liWidth); 90 } 91 else { 92 animate(ul, ul.offsetLeft - liWidth); 93 } 94 index += 1; 95 btnShow(index); 96 } 97 } 98 next.addEventListener("click",nextclick, false); 99 100 function btnShow(cur_index) { 101 for (var i = 0; i < ol.children.length; i++) { 102 ol.children[i].className = ' '; //取消全部li的類 103 } 104 ol.children[cur_index - 1].className = "current"; //給新的小圓點加上類 105 } 106 //7.再加上一個計時器,每隔一段時間就會觸發一次下一張的效果,來實現輪播 107 var timer; 108 function play() { 109 timer = setInterval(nextclick, 3000) 110 } 111 112 scroll.addEventListener("load", play(), false); //整個div全部加載完畢后開始 113 114 scroll.addEventListener("mouseenter", function () { //鼠標移入圖片是清除計時器 115 clearInterval(timer); 116 }, false); 117 118 scroll.addEventListener("mouseleave", function () { //鼠標移出圖片時再次啟動計時器 119 play(); 120 }, false); 121 122 //8.最后給小圓點加上事件,點第幾個輪播到第幾張 123 //小圓點的點擊事件 124 var olliclick = function () { 125 if (flag) { 126 flag = false; 127 var cur_li = document.getElementsByClassName("current"); 128 var lastid = cur_li[0].id; //當前的小圓點是第幾個 129 var distance = this.id - lastid; //計算當前小圓點與點擊的小圓點的距離(分正負) 130 if (distance == 0) { 131 flag = true; 132 } 133 else { 134 animate_ol(ul, distance); 135 } 136 } 137 } 138 139 //給所有的小圓點添加上點擊事件 140 var ollitimer = 1 141 var lis = ol.getElementsByTagName('li'); 142 for (ollitimer; ollitimer < lis.length+1; ollitimer++) { 143 var olli = document.getElementById(ollitimer); 144 olli.addEventListener("click", olliclick, false); 145 } 146 147 function animate_ol(obj, value) { //小圓點動畫函數 148 if (value > 0) { //判斷移動方向 149 var speed = -20*value; //使動畫時間一致 150 } 151 if (value < 0) { 152 var speed = -20*value; 153 } 154 var lastleft = obj.offsetLeft; 155 obj.timer = setInterval(function () { 156 var distance = Math.abs(value * liWidth) - Math.abs(obj.offsetLeft - lastleft); 157 //剩余需要移動的距離 158 if (distance < Math.abs(speed)) { 159 clearInterval(obj.timer); 160 if (value > 0) { 161 obj.style.left = obj.offsetLeft - distance + "px"; 162 flag = true; 163 } 164 if (value < 0) { 165 obj.style.left = obj.offsetLeft + distance + "px"; 166 flag = true; 167 } 168 } 169 else { 170 obj.style.left = obj.offsetLeft + speed + "px"; 171 } 172 }, 1); 173 index = index + value; 174 btnShow(index); 175 }
再對一下常見的鬼畜bug進行一下總結:
通過設置flag來防止多次點擊造成的計時器沖突,在點擊后將flag置為false,在動畫函數結束時再置為true,這樣只能在上一個點擊事件動畫結束后才會觸發第二次。