需求:
循環無縫自動輪播五張圖,按左右箭頭能夠手動切換圖片,鼠標點擊輪播圖下面按鈕 1 2 3 4 5會跳轉到對應的第1 2 3 4 5張圖片。鼠標放到輪播圖的圖片上時再也不自動輪播而且左右箭頭顯示出來,鼠標移開時左右箭頭隱藏掉而且自動輪播。
效果圖:javascript
<body>
<div class="container">
<div class="wrap">
<img src="./imgs/5.jpg" alt="5">
<img src="./imgs/1.jpg" alt="1">
<img src="./imgs/2.jpg" alt="2">
<img src="./imgs/3.jpg" alt="3">
<img src="./imgs/4.jpg" alt="4">
<img src="./imgs/5.jpg" alt="5">
<img src="./imgs/1.jpg" alt="1">
</div>
<div class="button">
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
</div>
<a href="javascript:void(0);" class="jt jt_left"><</a>
<a href="javascript:void(0);" class="jt jt_right">></a>
</div>
複製代碼
給a標籤加 javascript:void (0);
是爲了避免讓a標籤跳轉。
2. 定義樣式
主要目的:給總div、圖片區按鈕區div、圖片、按鈕、左右箭頭定義寬高,讓七個圖片並排顯示,五個按鈕位於圖片底部居中顯示,兩個箭頭分別到左右兩邊的適中位置顯示。html
/* 清除默認樣式 */
*{
margin: 0;
padding: 0;
text-decoration: none;
}
/* 總div */
div.container{
position: relative;
width: 600px;
height: 400px;
margin: 100px auto 0 auto;
box-shadow: 0 0 5px aqua;
overflow: hidden;
}
/* 圖片區 */
div.container div.wrap{
position: absolute;
width: 4200px;
height: 400px;
z-index: 1;
}
div.container div.wrap img{
width: 600px;
height: 400px;
float: left;
}
/* 按鈕區 */
div.container div.button{
position: absolute;
right: 225px;
bottom: 15px;
width: 150px;
height: 20px;
z-index: 2;
text-align: center;
}
div.container div.button span{
margin-left: 5px;
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: greenyellow;
text-align: center;
color: white;
cursor: pointer;
opacity: 0.6;
}
/* 輪播到哪張圖,哪一個按鈕有這個效果,與其餘按鈕有個區別。 */
div.container div.button span.on{
opacity: 1;
}
/* 箭頭區 */
div.container .jt{
position: absolute;
top: 40%;
color:greenyellow;
padding: 0px 14px;
font-size: 55px;
text-align: center;
z-index: 2;
display: none;
}
div.container .jt_left{
left: 10px;
}
div.container .jt_right{
right: 10px;
}
div.container:hover .jt{
display: block;
opacity: 0.4;
}
div.container .jt:hover{
opacity: 1;
}
複製代碼
爲了讓剛進頁面第一張圖顯示的是1.jpg,因此在圖片區圖裏面加個行內樣式,讓默認打開頁面顯示這個圖:
<div class="wrap" style="left:-600px">...</div>
此時效果是這樣,當鼠標移動到圖片上、箭頭處都有一些樣式:java
var wrap = document.getElementsByClassName('wrap')[0];
var newLeft = -600;
function next() {
setInterval(function(){
if(newLeft == -2400){
newLeft = 0;
}else{
newLeft = parseInt(wrap.style.left) - 600;
}
wrap.style.left = newLeft + 'PX';
},1000)
}
function prev() {
setInterval(function(){
if(newLeft == -600){
newLeft = -3000;
}else{
newLeft = parseInt(wrap.style.left) + 600;
}
wrap.style.left = newLeft + 'PX';
},1000)
}
複製代碼
第二步:讓輪播的時候各個圖片有運動軌跡地切換,而不是硬生生地從一張圖片變到另外一張圖片。
這裏須要用到我封裝好的一個運動函數startMove(),作成工具使用:git
function getStyle(obj, attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj, false)[attr];
}
}
//運動框架 startMove函數
function startMove(obj,json,fn){
clearInterval(obj.timer);
//開啓定時器
obj.timer = setInterval(function(){
var flag = true;
//遍歷json
for (var attr in json) {
//取當前值 iCur
var iCur = 0;
if (attr == 'opacity') {
iCur = Math.round(parseFloat(getStyle(obj, attr))*100);
}else{
iCur = parseInt(getStyle(obj, attr));
}
//算速度:iSpeed
//目標值:json[attr]
var iSpeed = (json[attr]-iCur)/8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
//檢測中止
if (iCur != json[attr]) {
flag = false
}
if (attr == 'opacity') {
obj.style.filter = 'alpha(opacity:'+iCur+iSpeed+')';
obj.style.opacity = (iCur+iSpeed)/100;
}else{
obj.style[attr] = iCur + iSpeed + 'px';
}
}
if (flag) {
clearInterval(obj.timer);
if (fn) {fn();}
}
},30)
}
複製代碼
這個封裝的運動函數這裏,加上個人註釋還看不懂代碼的,能夠去看看這個視頻,這講師講得很清楚:JS動畫效果
而後利用這個原理:當圖片往右輪播到第六張的時候,立刻讓第一張呈現出來,緊接着調用封裝好的運動函數讓從第一張圖運動切換到第二張。往左輪播時也是同樣的道理,當輪播到第一張的時候立刻讓第六張呈現出來,緊接着從第六張運動到第五張。這樣子從視覺上看來就是五張圖片一直循環無縫輪播下去的
這是也爲何要用七張圖片,而且第一張圖片和第六張同樣,第七張和第二張同樣的緣由。 代碼以下:github
var wrap = document.getElementsByClassName('wrap')[0];
var newLeft = -600;
function next() {
setInterval(function () {
if (newLeft == -3000) {
newLeft = 0;
wrap.style.left = newLeft + 'px';
}
newLeft -= 600;
startMove(wrap, {
"left": newLeft
})
// wrap.style.left = newLeft + 'PX';
}, 3000)
}
function prev() {
setInterval(function () {
if (newLeft == 0) {
newLeft = -3000;
wrap.style.left = newLeft + 'px';
}
newLeft += 600;
startMove(wrap, {
"left": newLeft
});
}, 3000)
}
複製代碼
第三步:使當鼠標移到圖片上時,中止自動輪播而讓點擊幾回左右箭頭來控制往左右一張一張地輪播幾張。
核心原理:清除定時器,綁定click、onmouseenter、onmouseleave事件,重構下代碼封裝出往右往左輪播函數和自動輪播函數。
往右輪播函數:json
function next() {
if (newLeft == -3000) {
newLeft = 0;
wrap.style.left = newLeft + 'px';
}
newLeft -= 600;
startMove(wrap, {
"left": newLeft
});
}
複製代碼
往左輪播函數:bash
function prev() {
if (newLeft == 0) {
newLeft = -3000;
wrap.style.left = newLeft + 'px';
}
newLeft += 600;
startMove(wrap, {
"left": newLeft
});
}
複製代碼
自動播放函數:閉包
var timer = null;
function autoPlay() {
timer = setInterval(function () {
next();
}, 2000)
} /* 自動播放 */
複製代碼
綁定各個事件:框架
container.addEventListener('mouseenter', function () {
clearInterval(timer);
}, false)
container.addEventListener('mouseleave', function () {
autoPlay();
}, false)
left.addEventListener('click', function () {
prev();
})
right.addEventListener('click', function () {
next();
})
複製代碼
第四步:函數
//處理按鈕
var index = 0;
var len = dot.length;
function setCurrentDot(){
for (var m = 0; m < len; m++){
dot[m].className = '';
}
dot[index].className = 'on';
}
setCurrentDot();
複製代碼
此時調用了這個函數的話,就等於剛進入頁面的時候默認顯示的第一張圖片也是默認讓第一個按鈕有'on'類的效果。
那怎麼讓當視覺上移動到第A張圖時,就讓此時這第A個按鈕的類型爲'on'呢?
能夠在輪播一次的函數里加入修改index哨兵的值而且調用setCurrentDot()函數。在next()中:
index++;
if(index === 5){
index = 0;
}
setCurrentDot();
複製代碼
在prev()中:
index--;
if(index === -1){
index = 4;
}
setCurrentDot();
複製代碼
最後,實現點到哪一個按鈕時,該按鈕有類爲'on'的效果,而且跳轉到視覺上的第幾張圖。
核心思路:當點擊該按鈕時,好比點了第三個按鈕,那麼此時應該顯示的圖片應該是視覺上第三張圖片也就是七張圖片中的第四張,第四張對應的wrap的left爲-1800px,而後找出對應的規律,此時的newLeft就應該爲:-600 * (x + 1)。那麼無論在點擊按鈕前已經輪播到哪裏了,只要在點擊後,使用運動函數startMove()移動到這個newLeft位置處就好了。按例子來講此時的哨兵index也等於3,由於點了第幾個按鈕確定就第幾個按鈕有'on'類咯。
根據核心思路寫出代碼爲(這裏須要注意綁定事件時的閉包問題):
// 點到哪一個按鈕時,該按鈕有類爲'on'的效果,而且跳轉到視覺上的第幾張圖。
for (var s = 0; s < len; s++){
(function(s){
dot[s].addEventListener('click',function(){
newLeft = -600 * (s + 1);
startMove(wrap,{"left":newLeft});
index = s;
setCurrentDot();
},false)
}(s))
}
複製代碼
寫到這裏,因此需求就作完了。
思路就是這樣,重要的不是代碼,是分析邏輯。 源碼已傳到github,但願對您有幫助的~