今天分享前端開發(fā)學(xué)習(xí)中的一個很經(jīng)典的案例——原生JS實現(xiàn)無縫輪播圖鸭蛙。
需求:
1.鼠標(biāo)移入輪播圖時左右兩邊顯示上一頁下一頁按鈕较屿,移出時隱藏
2.鼠標(biāo)點擊箭頭隧魄,圖片發(fā)生輪播
3.點擊號碼,切換到指定圖片
4.鼠標(biāo)移出吝镣,圖片每隔一定時間自動輪播
5.當(dāng)圖片輪播到最后或最前一張的時候堤器,圖片無縫循環(huán)切換
<div class="all" id='box'>
<div class="screen">
<ul>
<li><img src="" width="500" height="200" style="background-color: yellowgreen;"/></li>
<li><img src="" width="500" height="200" style="background-color: pink;"/></li>
<li><img src="" width="500" height="200" style="background-color: skyblue;"/></li>
<li><img src="" width="500" height="200" style="background-color: greenyellow;"/></li>
<li><img src="" width="500" height="200" style="background-color: plum;"/></li>
<li><img src="" width="500" height="200" style="background-color: orange;"/></li>
</ul>
<ol>
<li class="current">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ol>
</div>
<div id="arr"><span id="left"><</span><span id="right">></span></div>
</div>
CSS樣式:樣式部分比較簡單,重點讓li標(biāo)簽浮動并排末贾,然后在盒子(類名為screen的div)里顯示其中一張,其他的隱藏(overflow:hidden)整吆,整個輪播思想就是移動整個ul標(biāo)簽拱撵。
<style type="text/css">
* {
padding: 0;
margin: 0;
list-style: none;
border: 0;
}
.all {
width: 500px;
height: 200px;
padding: 7px;
border: 1px solid #ccc;
margin: 100px auto;
position: relative;
}
.screen {
width: 500px;
height: 200px;
overflow: hidden;
position: relative;
}
.screen li {
width: 500px;
height: 200px;
overflow: hidden;
float: left;
}
.screen ul {
position: absolute;
left: 0;
top: 0px;
width: 3000px;
}
.all ol {
position: absolute;
right: 10px;
bottom: 10px;
line-height: 20px;
text-align: center;
}
.all ol li {
float: left;
width: 20px;
height: 20px;
background: #fff;
border: 1px solid #ccc;
margin-left: 10px;
cursor: pointer;
}
.all ol li.current {
background: yellow;
}
#arr {
display: none;
}
#arr span {
width: 40px;
height: 40px;
position: absolute;
left: 5px;
top: 50%;
margin-top: -20px;
background: #000;
cursor: pointer;
line-height: 40px;
text-align: center;
font-weight: bold;
font-family: '黑體';
font-size: 30px;
color: #fff;
opacity: 0.3;
border: 1px solid #fff;
}
#arr #right {
right: 5px;
left: auto;
}
</style>
JS處理:
第一步:完成輪播圖事件的添加 :用一個全局變量index記錄當(dāng)前需要展示的圖片的索引
(1)鼠標(biāo)移入移出事件:鼠標(biāo)移入,顯示左右切換按鈕表蝙,移出時隱藏
(2)上一頁下一頁按鈕點擊事件點擊下一頁:index++拴测,點擊上一頁:index--
(3)頁碼點擊事件:切換指定圖片
第二步:完成上一頁和下一頁
(1)點擊移動之前給ul添加邊界檢測:否則點擊下一頁會無限往右滾動
(2)修改當(dāng)前索引(自增/自減),索引表示的是當(dāng)前ul應(yīng)該展示第幾張圖片
(3)移動ul(目標(biāo)距離 = -index * screen的寬度)
(4)頁碼保持同步(當(dāng)前顯示的是第幾張圖片府蛇,下方頁碼對應(yīng)索引高亮)
第三步:完成無限輪播 核心思想:n+1
(1)常規(guī)思路:圖片滾動時集索,當(dāng)滾動到最后一張時,我們偷偷的快速改變ul的位置到第一張(不要動畫汇跨,瞬間改變)
ul.style.left = '0px'; //ul回到初始位置
index = 0; //index恢復(fù)到0
(2)問題發(fā)現(xiàn):這種方式可以實現(xiàn)無限輪播务荆,但是在下一輪無限的時候第一張會被跳過去
原因:我們手動改變了index為0,而動畫又需要index+1穷遂,所以會錯過index為0的那一張
(3)解決方案:我們在最后一張圖片的后面加上第一張圖片(第6張)可以讓用戶看到滾動效果函匕,然后滾動到第六張時,再改變ul回到初始位置
好處:①用戶可以看到滾動效果蚪黑,不影響體驗; ②剛好第6張與第一張是同一張圖片盅惜,快速改變位置不會造成動畫的閃現(xiàn)
(4)當(dāng)圖片index為最后一張的的時候中剩,頁碼應(yīng)該顯示第一個,因為最后一張和第一張是同一張圖片
第四步:完成點擊頁碼跳轉(zhuǎn)
(1)點擊的是第幾個頁碼抒寂,移動動畫的目標(biāo)距離 = -index * screen.offsetWidth
(2)排他思想改變頁碼樣式
(3)頁碼的下標(biāo)需要與圖片下標(biāo)index保持一致结啼,否則會產(chǎn)生沖突,即點擊頁碼的時候屈芜,要讓圖片下標(biāo)index與頁碼下標(biāo)一致
第五步:自動無限輪播
相當(dāng)于每隔一段時間自動點擊下一頁按鈕妆棒,代碼邏輯完全不變
(1)將輪播代碼封裝成一個函數(shù)
(2)開啟定時器,每隔一段時間執(zhí)行這個函數(shù)
(3)鼠標(biāo)移入時清除定時器沸伏,移出時開啟定時器
<script>
// 1.獲取頁面對應(yīng)的元素
var box=document.getElementById("box"); //最外部大盒子
var arr=document.getElementById("arr");
var screen=document.getElementsByClassName("screen")[0]; //輪播圖顯示區(qū)域div
var ul=document.getElementsByTagName("ul")[0]; //顯示圖片的ul
var ol=document.getElementsByTagName("ol")[0]; //顯示頁碼的ol
var left=document.getElementById("left"); //上一張箭頭
var right=document.getElementById("right"); //下一張箭頭
var index=0; ////聲明一個變量記錄圖片的索引糕珊,默認第0張圖片
//2.給box添加鼠標(biāo)移入和移出事件
//2.1 鼠標(biāo)移入
box.onmouseover= function () {
arr.style.display="block"; //顯示上一頁下一頁箭頭
clearInterval(timeId); //清除定時器(即鼠標(biāo)移入時,圖片要停止自動輪播)
};
//2.2 鼠標(biāo)移出
box.onmouseout= function () {
arr.style.display="none"; //隱藏箭頭
timeId=setInterval(scroll,2000); //重啟定時器(鼠標(biāo)移出毅糟,圖片要恢復(fù)自動輪播)
};
//3.給上一頁下一頁箭頭添加點擊事件
//3.1 下一頁红选,圖片向左輪播
right.onclick= function () {
scroll();
};
//3.2 上一頁,圖片向右輪播
left.onclick= function () {
//(1)邊界檢測姆另,如果當(dāng)前已經(jīng)是第一張喇肋,則不做任何處理
if(index==0){
//無限輪播原理:如果當(dāng)前是第一張,則偷偷修改ul的位置是最后一張(第一張與最后一張是同一張圖片)
index=ul.children.length-1; //index恢復(fù)到最后一張
ul.style.left=-index*screen.offsetWidth+"px"; ////ul回到最后一張位置
}
//(2)索引自減
index--;
// (3)向左移動ul:目標(biāo)距離 = -screen的寬度 * 索引
animationMove(ul,-index*screen.offsetWidth,10);
indexShow(); //同步頁碼樣式
};
//4.給頁碼添加點擊事件
for(var i=0;i<ol.children.length;i++){
//4.1 循環(huán)遍歷數(shù)組時給每一個頁碼添加一個liIndex屬性記錄下標(biāo)
ol.children[i].liIndex=i;
ol.children[i].onclick= function () {
index=this.liIndex-1;
scroll();
};
}
var timeId=setInterval(scroll,2000);
// 封裝一個向右輪播的函數(shù)
function scroll(){
//(1)邊界檢測:如果當(dāng)前已經(jīng)是最后一張(第n+1張,n代表需要輪播的圖片數(shù)量)
if(index==ul.children.length-1){
//無限輪播的原理就是滾動到最后一張的時候迹辐,偷偷快速的改變ul的位置到第一張(不要任何動畫蝶防,一瞬間改變)
index=0; //index恢復(fù)到0
ul.style.left=0+"px"; //ul回到初始位置
}
// (2)索引自增
index++;
// (3)向右移動ul:目標(biāo)距離 = -screen的寬度 * 索引
animationMove(ul,-index*screen.offsetWidth,10);
indexShow(); //同步頁碼樣式
}
//5.頁碼樣式保持同步:排他思想(當(dāng)前頁碼添加樣式,其他頁碼移除該樣式)
function indexShow(){
for(var i=0;i<ol.children.length;i++){
if(i==index){
ol.children[i].classList.add("current");
}else{
ol.children[i].classList.remove("current");
}
//特殊情況:當(dāng)index為最后一張的時候明吩,頁碼應(yīng)該顯示第一張
if(index==ul.children.length-1){
ol.children[0].classList.add("current");
}
}
}
// 封裝一個滾動動畫函數(shù)
function animationMove(obj,target,speed){
clearInterval(obj.timeId); //每次執(zhí)行動畫先清除原有的定時器
obj.timeId=setInterval(function () {
var currentLeft=obj.offsetLeft; //獲取當(dāng)前位置
var isLeft=currentLeft>target?true:false; //是否往左走
if(isLeft){
currentLeft-=10; //往左走
}else{
currentLeft+=10; //往右走
}
if(isLeft?currentLeft>target:currentLeft<target){
obj.style.left=currentLeft+"px"; //如果當(dāng)前位置不是在目標(biāo)位置則進行位置處理
}else{
clearInterval(obj.timeId);
obj.style.left=target+"px";
}
},speed);
}
</script>