一、概念
現在一般的電商網站的首頁都會有一個輪播圖,如下圖這樣

這幅圖可以拆分為三個功能
1、通過點擊數字切換圖片。
2、通過點擊左右按鈕切換圖片。
3、鼠標沒有停留在相框范圍內時,自動輪詢切換圖片。
下面針對這三個功能,一個個單獨講解。
二、點擊數字切換圖片
效果

代碼
公共common.js,下面所有的代碼都會引用這個js。
//根據id獲取元素對象
function my$(id) {
return document.getElementById(id);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0
}
ul {
list-style: none
}
.box { /*設置最外層div的大小 對齊方式 邊框*/
width: 730px;
height: 454px;
margin: 100px auto;
padding: 5px;
border: 1px solid #ccc;
}
.inner { /*相框大小設置*/
width: 730px;
height: 454px;
background-color: pink;
overflow: hidden;
position: relative;
}
/* 這里width的寬度一定要比圖片的總寬度要寬,這里一共有5張圖,設置600%也是沒有問題的。
不然因為圖片設置左浮動,如果寬度不夠那么就會溢出換行。如果父元素設置 overflow: hidden;那么也無法實現輪播效果*/
.inner ul {
width: 1000%;
position: absolute;
}
.inner li { /*圖片左浮動*/
float: left;
}
.square { /*絕對定位*/
position: absolute;
right: 10px;
bottom: 10px;
}
.square span { /*行轉塊*/
display: inline-block;
width: 16px;
height: 16px;
background-color: #fff;
text-align: center;
line-height: 16px;
cursor: pointer;
}
.square span.current { /*設置當前按鈕顏色*/
background-color: orangered;
color: #fff;
}
</style>
</head>
<body>
<div class="box" id="box">
<div class="inner"><!--相框-->
<ul>
<li><a href="#"><img src="images/1.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/2.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/3.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/4.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/5.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/6.jpg" alt=""/></a></li>
</ul>
<div class="square"> <!-- 按鈕,這里寫死6個按鈕並不合理 因為上面圖片不是固定的,應該根據上面進行設置個數 會優化 -->
<span class="current">1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
</div>
</div>
</div>
<!-- 引用公共js -->
<script src="common.js"></script>
<script>
//獲取最外面的div
var box = my$("box");
//獲取相框
var inner = box.children[0];
//獲取相框的寬度
var imgWidth = inner.offsetWidth;
//獲取ul
var ulObj = inner.children[0];
//獲取所有的span標簽
var spanObjs = inner.children[1].children;
//循環遍歷所有的span標簽,注冊鼠標進入的事件
for (var i = 0; i < spanObjs.length; i++) {
//循環的時候把索引值保存在每個span的自定義屬性中
spanObjs[i].setAttribute("index", i);
//注冊鼠標進入事件
spanObjs[i].onmouseover = function () {
//先干掉所有的span的背景顏色
for (var j = 0; j < spanObjs.length; j++) {
//移除了每個span的類樣式
spanObjs[j].removeAttribute("class");
}
//設置當前的span的背景顏色
this.className = "current";
//移動ul(每個圖片的寬*鼠標放在這個按鈕的索引值)
//獲取當前鼠標進入的span的索引
var index = this.getAttribute("index");
// 為什么這里是負數
animate(ulObj, -index * imgWidth);
};
}
//設置任意的一個元素,移動到指定的目標位置
function animate(element, target) {
clearInterval(element.timeId);
//定時器的id值存儲到對象的一個屬性中
element.timeId = setInterval(function () {
//獲取元素的當前的位置,數字類型
// 如果第一次進定時任務這里值為0 因為d當前元素的父類設置了position屬性,
// 那么offsetLeft為元素邊框外側到父元素邊框內側的距離,那么這里就為0
var current = element.offsetLeft;
//每次移動的距離 指的是切換圖片每次移動10px,定時任務為20毫米執行一次,就是20毫秒移動10px
var step = 10;
//這里設計到是左移動圖片還是右移動圖片 如果1跳到2就是左移動 2跳到1就是右移動
step = current < target ? step : -step;
console.log("target=" + target);
console.log("current=" + current);
//當前移動到位置
current += step;
//如果當前移動的絕對值小於10 那么就要關閉定時器 好比從1點到2 已經移動到第二張圖片了那么就需要關閉定時器
if (Math.abs(current - target) > Math.abs(step)) {
element.style.left = current + "px";
} else {
//清理定時器
clearInterval(element.timeId);
//直接到達目標
element.style.left = target + "px";
}
}, 20);
}
</script>
</body>
</html>
上面代碼中的注釋說明的已經挺清楚的了。,這里再詳細解釋下面這段代碼
animate(ulObj, -index * imgWidth) // 為什么這里傳入的是負數

畫了這幅圖應該把這里原理講的蠻清楚的。
三、點擊左右按鈕切換圖片
效果

這里的效果主要有兩點
1、在鼠標沒有移動到相框里時候,左右按鈕消失(焦點事件)
2、點擊左按鈕切換到下一張圖片,點擊右按鈕時候切換到上一張圖片(這里注釋掉了overflow: hidden;屬性 所以所有圖片都會顯示)
代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body, ul, ol, li, img {
margin: 0;
padding: 0;
list-style: none;
}
#box {
width: 520px;
height: 280px;
padding: 5px;
position: relative;
border: 1px solid #ccc;
margin: 100px auto 0;
}
.ad {
width: 520px;
height: 280px;
/*overflow: hidden;*/
position: relative;
}
#box img {
width: 520px;
}
.ad ol {
position: absolute;
right: 10px;
bottom: 10px;
}
.ad ol li {
width: 20px;
height: 20px;
line-height: 20px;
border: 1px solid #ccc;
text-align: center;
background: #fff;
float: left;
margin-right: 10px;
cursor: pointer;
_display: inline;
}
.ad ol li.current {
background: yellow;
}
.ad ul li {
float: left;
}
.ad ul {
position: absolute;
top: 0;
width: 2940px;
}
.ad ul li.current {
display: block;
}
#focusD {
display: none;
}
#focusD 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;
}
#focusD #right {
right: 5px;
left: auto;
}
</style>
</head>
<body>
<div id="box" class="all">
<div class="ad">
<ul id="imgs">
<li><img src="images/01.jpg"/></li>
<li><img src="images/02.jpg"/></li>
<li><img src="images/03.jpg"/></li>
<li><img src="images/04.jpg"/></li>
<li><img src="images/05.jpg"/></li>
</ul>
</div><!--相框-->
<div id="focusD"><span id="left"><</span><span id="right">></span>
</div>
</div>
<script src="common.js"></script>
<script>
//獲取最外面的div
var box = my$("box");
//獲取相框
var ad = box.children[0];
//獲取相框的寬度
var imgWidth = ad.offsetWidth;
//獲取ul
var ulObj = ad.children[0];
//獲取左右焦點的div
var focusD = my$("focusD");
//顯示和隱藏左右焦點的div----為box注冊事件
box.onmouseover = function () {
focusD.style.display = "block";
};
box.onmouseout = function () {
focusD.style.display = "none";
};
//點擊右邊按鈕
var index=0;
my$("right").onclick = function () {
//index最終等於 0,1,2,3,4
if(index<ulObj.children.length-1){
index++;
animate(ulObj,-index*imgWidth);
}
};
//點擊左邊按鈕
my$("left").onclick = function () {
//idex最終等於 4,3,2,1,0
if(index>0){
index--;
animate(ulObj,-index*imgWidth);
}
};
//設置任意的一個元素,移動到指定的目標位置
function animate(element, target) {
clearInterval(element.timeId);
//定時器的id值存儲到對象的一個屬性中
element.timeId = setInterval(function () {
//獲取元素的當前的位置,數字類型
var current = element.offsetLeft;
//每次移動的距離
var step = 10;
step = current < target ? step : -step;
//當前移動到位置
current += step;
if (Math.abs(current - target) > Math.abs(step)) {
element.style.left = current + "px";
} else {
//清理定時器
clearInterval(element.timeId);
//直接到達目標
element.style.left = target + "px";
}
}, 20);
}
</script>
</body>
</html>
四、自動輪詢切換圖片
效果

這里的效果主要有兩點
1、當鼠標不在相框范圍內,相框中的圖片進行自動切換圖片
2、當鼠標進入相框范圍內,此時相框中的圖片停止不再移動
代碼
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
img {
vertical-align: top;
}
/*取消圖片底部3像素距離*/
.box {
width: 300px;
height: 200px;
margin: 100px auto;
background-color: pink;
border: 1px solid red;
position: relative;
overflow: hidden;
}
.box ul li {
float: left;
}
.box ul {
width: 1500px;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="box" id="screen">
<ul>
<li><img src="imagess/01.jpg" alt=""/></li>
<li><img src="imagess/02.jpg" alt=""/></li>
<li><img src="imagess/03.jpg" alt=""/></li>
<li><img src="imagess/04.jpg" alt=""/></li>
<li><img src="imagess/04.jpg" alt=""/></li>
</ul>
</div>
<script src="common.js"></script>
<script>
var current = 0;//只聲明了一次
function f1() {
var ulObj = my$("screen").children[0];
current -= 10;
//每張圖片寬度為300 當第四張圖片播放結束就又重新開始播放第一張
if (current < -1200) {
ulObj.style.left = 0 + "px";
current = 0;
} else {
ulObj.style.left = current + "px";
}
}
//最開始沒有獲取焦點,那么通過定時任務自動移動圖片
var timeId=setInterval(f1, 30);
//鼠標獲得焦點
my$("screen").onmouseover=function () {
//停止
clearInterval(timeId);
};
//鼠標失去焦點
my$("screen").onmouseout=function () {
//繼續
timeId=setInterval(f1, 30);
};
</script>
</body>
</html>
原理
實現自動輪播有一個需要注意的原理
那就是第一張圖需要和最后一張圖是一樣的,這里有五張圖,那么第一張圖和第五張圖其實同一張圖,當第四張圖播放完即將切到第五張圖的時候,
其實就是切換到第一張圖,這樣做的目的就是讓整個循環輪播變的很自然
如果這里第五張和第一張圖不一樣就會有一閃的。

很明顯當第四張播放完切換到第一張的圖的時候,會有一閃的動作,使整個動作並不自然。
五、完整示例
效果最頂上已經演示了,這里展示代碼就可以。
代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<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: #DB192A;
}
#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>
</head>
<body>
<div class="all" id='box'>
<div class="screen"><!--相框-->
<ul>
<li><img src="images/1.jpg" width="500" height="200"/></li>
<li><img src="images/2.jpg" width="500" height="200"/></li>
<li><img src="images/3.jpg" width="500" height="200"/></li>
<li><img src="images/4.jpg" width="500" height="200"/></li>
<li><img src="images/5.jpg" width="500" height="200"/></li>
</ul>
<ol>
</ol>
</div>
<div id="arr"><span id="left"><</span><span id="right">></span></div>
</div>
<script src="common.js"></script>
<script>
//獲取最外面的div
var box = my$("box");
//獲取相框
var screen = box.children[0];
//獲取相框的寬度
var imgWidth = screen.offsetWidth;
//獲取ul
var ulObj = screen.children[0];
//獲取ul中的所有的li
var list = ulObj.children;
//獲取ol
var olObj = screen.children[1];
//焦點的div
var arr = my$("arr");
var pic = 0;//全局變量
//創建小按鈕----根據ul中的li個數
for (var i = 0; i < list.length; i++) {
//創建li標簽,加入到ol中
var liObj = document.createElement("li");
olObj.appendChild(liObj);
liObj.innerHTML = (i + 1);
//在每個ol中的li標簽上添加一個自定義屬性,存儲索引值
liObj.setAttribute("index", i);
//注冊鼠標進入事件
liObj.onmouseover = function () {
//先干掉所有的ol中的li的背景顏色
for (var j = 0; j < olObj.children.length; j++) {
olObj.children[j].removeAttribute("class");
}
//設置當前鼠標進來的li的背景顏色
this.className = "current";
//獲取鼠標進入的li的當前索引值
pic = this.getAttribute("index");
//移動ul
animate(ulObj, -pic * imgWidth);
};
}
//設置ol中第一個li有背景顏色
olObj.children[0].className = "current";
//克隆一個ul中第一個li,加入到ul中的最后=====克隆
ulObj.appendChild(ulObj.children[0].cloneNode(true));
//自動播放
var timeId= setInterval(clickHandle,1000);
//鼠標進入到box的div顯示左右焦點的div
box.onmouseover = function () {
arr.style.display = "block";
//鼠標進入廢掉之前的定時器
clearInterval(timeId);
};
//鼠標離開到box的div隱藏左右焦點的div
box.onmouseout = function () {
arr.style.display = "none";
//鼠標離開自動播放
timeId= setInterval(clickHandle,1000);
};
//右邊按鈕
my$("right").onclick =clickHandle;
function clickHandle() {
//如果pic的值是5,恰巧是ul中li的個數-1的值,此時頁面顯示第六個圖片,而用戶會認為這是第一個圖,
//所以,如果用戶再次點擊按鈕,用戶應該看到第二個圖片
if (pic == list.length - 1) {
//如何從第6個圖,跳轉到第一個圖
pic = 0;//先設置pic=0
ulObj.style.left = 0 + "px";//把ul的位置還原成開始的默認位置
}
pic++;//立刻設置pic加1,那么此時用戶就會看到第二個圖片了
animate(ulObj, -pic * imgWidth);//pic從0的值加1之后,pic的值是1,然后ul移動出去一個圖片
//如果pic==5說明,此時顯示第6個圖(內容是第一張圖片),第一個小按鈕有顏色,
if (pic == list.length - 1) {
//第五個按鈕顏色干掉
olObj.children[olObj.children.length - 1].className = "";
//第一個按鈕顏色設置上
olObj.children[0].className = "current";
} else {
//干掉所有的小按鈕的背景顏色
for (var i = 0; i < olObj.children.length; i++) {
olObj.children[i].removeAttribute("class");
}
olObj.children[pic].className = "current";
}
};
//左邊按鈕
my$("left").onclick = function () {
if (pic == 0) {
pic = 5;
ulObj.style.left = -pic * imgWidth + "px";
}
pic--;
animate(ulObj, -pic * imgWidth);
//設置小按鈕的顏色---所有的小按鈕干掉顏色
for (var i = 0; i < olObj.children.length; i++) {
olObj.children[i].removeAttribute("class");
}
//當前的pic索引對應的按鈕設置顏色
olObj.children[pic].className = "current";
};
//設置任意的一個元素,移動到指定的目標位置
function animate(element, target) {
clearInterval(element.timeId);
//定時器的id值存儲到對象的一個屬性中
element.timeId = setInterval(function () {
//獲取元素的當前的位置,數字類型
var current = element.offsetLeft;
//每次移動的距離
var step = 10;
step = current < target ? step : -step;
//當前移動到位置
current += step;
if (Math.abs(current - target) > Math.abs(step)) {
element.style.left = current + "px";
} else {
//清理定時器
clearInterval(element.timeId);
//直接到達目標
element.style.left = target + "px";
}
}, 10);
}
</script>
</body>
</html>
``` 你如果願意有所作為,就必須有始有終。(27) ```