JS原生實(shí)現(xiàn)輪播圖的幾種方法
輪播圖
主要思想就是:
在大的容器里,裝著一個(gè)很長(zhǎng)的表,表是容器寬度的整數(shù)倍。
然后通過(guò)更改列表樣式里的left屬性來(lái)實(shí)現(xiàn)左右滑動(dòng)。
本文旨在控制滑動(dòng)五張圖片,但在html中使用了七張圖片,第一張和最后一張是有重復(fù)的,至于原因會(huì)在下面解釋。

通過(guò)給容器設(shè)定overflow:hidden屬性來(lái)保證只顯示容器視口大小的一張圖片。
<body> <div id="container"> /*容器*/ <div id="wrap" style="left: -400px;"> /*存放圖片的列表*/ <div class="item item5">l5</div> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> <div class="item item1">r1</div> </div> </div> <div id="key"> /*設(shè)置按鈕*/ <div id="list"> /*點(diǎn)擊小圓圈切換到固定圖片*/ <div class="btn1 btnNum">1</div> <div class="btn2 btnNum">2</div> <div class="btn3 btnNum">3</div> <div class="btn4 btnNum">4</div> <div class="btn5 btnNum">5</div> </div> <div id="btn"> /*向左切換和向右切換的按鈕*/ <button class="left">←</button> <button class="right">→</button> </div> </div> </body>
CSS:
可以給wrap列表設(shè)置flex屬性,讓圖片在一行顯示。其他布局可以按自己需求來(lái)做。
注意在定義id="wrap"d的節(jié)點(diǎn)中設(shè)置了內(nèi)聯(lián)樣式left。因?yàn)樵谇袚Q圖片的時(shí)候我用到的是left屬性,而如果不設(shè)置left的話,在DOM設(shè)置style時(shí)是找不到left屬性的。
<style>
#container {
width: 400px;
height: 300px;
border: 8px rgb(8, 8, 8) solid;
margin: 0 auto;
margin-top: 150px;
overflow: hidden;
position: relative;
}
#wrap {
width: 2800px;
height: 300px;
display: flex;
position: relative;
}
.item {
flex: 1;
width: 400px;
height: 300px;
}
.item1 {
background-color: rosybrown;
}
.item2 {
background-color: rgb(12, 226, 37);
}
.item3 {
background-color: rgb(212, 221, 29);
}
.item4 {
background-color: rgb(61, 27, 182);
}
.item5 {
background-color: rgb(221, 23, 145);
}
#key {
width: 400px;
height: 300px;
margin: 0 auto;
}
#list {
width: 400px;
height: 40px;
display: flex;
justify-content: center;
}
#list div {
margin-top: 10px;
margin-left: 10px;
width: 20px;
height: 20px;
background-color: rgb(13, 162, 221);
text-align: center;
border-radius: 45%;
opacity: 0.6;
}
#list div:hover {
cursor: pointer;
opacity: 1;
}
#btn {
width: 400px;
text-align: center;
}
</style>
這是完整的樣式

每種顏色代表一張圖片,且按序標(biāo)了序號(hào)。起始位置是第二張圖片。
至于為什么第一張和最后一張有額外重復(fù)的一張放在兩端,是為了在做滑動(dòng)效果的時(shí)候,最后一張(倒數(shù)第二張,粉紫色)可以繼續(xù)向右順滑的滑到第一張(其實(shí)是本圖的第二張,淺棕色的)。第一張(本圖第二張,淺棕色)向左滑動(dòng)時(shí)可以順滑的滑到最后一張(實(shí)則倒數(shù)第二張)。繼續(xù)往下看。
1. 多種輪播方式
輪播必然離開(kāi)不了定位,以及修改wrap列表的left屬性,使其移動(dòng)。
先初始化幾個(gè)數(shù)據(jù)
var wrap = document.getElementById('wrap');
var nowleft = -400; //用于存放當(dāng)前列表的left的值
var currIndex = 1; //用于存放當(dāng)前是第幾個(gè)圖片
//定位到幾個(gè)按鈕
var btnNum = document.getElementsByClassName('btnNum'); //小圓圈
var right = document.getElementsByClassName('right')[0]; //向右滑的按鈕
var left = document.getElementsByClassName('left')[0]; //向左滑的按鈕
1.1 定時(shí)自動(dòng)輪播效果
只講向左自動(dòng)滑動(dòng)的效果
既然是自動(dòng)輪播的,那必然少不了setInterval()定時(shí)器讓其持續(xù)輪播。
function next() {
setInterval(function() { //設(shè)置每?jī)擅肭袚Q一次圖片
wrap.style.transition = 'left 1s' //設(shè)定有過(guò)渡滑動(dòng)的效果
nowleft = parseInt(wrap.style.left) - 400; //切換一次后nowleft應(yīng)該減少(即向左滑)一個(gè)圖片的寬度
wrap.style.left = nowleft + 'px'; //然后將nowleft賦值給wrap的left屬性
if(parseInt(wrap.style.left) == -2400) { //判斷到最后一個(gè)后,偷偷變回到最開(kāi)頭的位置
setTimeout(() => {
wrap.style.transition = 'none' //因?yàn)槭峭低底兓厝?,所以要取消過(guò)渡效果
nowleft = -400;
wrap.style.left = nowleft + 'px'
},1200) //保證定時(shí)器的時(shí)間大于過(guò)度的時(shí)間且小于每次輪換的時(shí)間
}
},2000)
}
/由于wrap.style.left 返回的是帶px的字符串,所以用parseInt可以取得前面的數(shù)值/
1.2 按向右滑動(dòng)按鈕
right.addEventListener('click',function() {
if(nowleft >= -2000){ //判斷是否到最后一個(gè)圖了,沒(méi)有的話就開(kāi)始滑動(dòng)
nowleft -= 400;
wrap.style.transition = 'left 1s';
wrap.style.left = nowleft + 'px';
}
if(nowleft == -2400) { //如果到最后一個(gè)圖了,就偷偷換回第一張圖
setTimeout(() => {
wrap.style.transition = 'none';
nowleft = -400;
wrap.style.left = nowleft + 'px';
},1020)
}
})
1.3 小圓圈切換圖片
for(let i = 0; i < btnNum.length; i++) {
btnNum[0].style.opacity = 1;
btnNum[i].addEventListener('click',function() {
wrap.style.transition = 'left 1s';
for(let j = 0; j < btnNum.length; j++) {
btnNum[j].style.opacity = '0.6';
}
btnNum[i].style.opacity = 1;
nowleft = nowleft - (i+1 - currIndex)*400;
currIndex = i + 1;
wrap.style.left = nowleft + 'px';
})
其實(shí)本文在控制從最后一個(gè)圖偷偷換回第一張圖的操作是有缺陷的,因?yàn)橐芽匦蛱?hào)5的圖滑動(dòng)到序號(hào)為r1的圖是需要1s的,然而wrap.style.left是直接發(fā)生變化的,不會(huì)隨著過(guò)渡期間發(fā)生位移而left一直變化。所以把控序號(hào)5完整滑動(dòng)到r1后再偷偷切換到序號(hào)1的時(shí)間是有些難控制的。
而且比如從序號(hào)1連續(xù)點(diǎn)擊3下是可以切換到序號(hào)4的。然是從序號(hào)5連續(xù)點(diǎn)擊3下是不可以的,在r1切換到序號(hào)1的時(shí)候是無(wú)法響應(yīng)點(diǎn)擊效果的,因此此處交互差異會(huì)容易感到別扭。
如果想改善這個(gè)別扭的bug,可以用下防抖來(lái)改善。
到此這篇關(guān)于JS原生實(shí)現(xiàn)輪播圖的幾種方法的文章就介紹到這了,更多相關(guān)JS原生輪播圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中兩個(gè)感嘆號(hào)的作用說(shuō)明
用兩個(gè)感嘆號(hào)的作用就在于,如果明確設(shè)置了o中flag的值(非null/undefined/0""/等值),自然test就會(huì)取跟o.flag一樣的值;如果沒(méi)有設(shè)置,test就會(huì)默認(rèn)為false,而不是null或undefined2011-12-12
解決Babylon.js中AudioContext was not allowed&nbs
這篇文章主要介紹了解決Babylon.js中AudioContext was not allowed to start異常問(wèn)題方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
JavaScript之Map和Set_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了JavaScript之Map和Set的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
JS設(shè)計(jì)模式之狀態(tài)模式概念與用法分析
這篇文章主要介紹了JS設(shè)計(jì)模式之狀態(tài)模式概念與用法,簡(jiǎn)單講述了狀態(tài)模式的概念、功能、應(yīng)用場(chǎng)景并結(jié)合javascript實(shí)例形式分析了狀態(tài)模式的簡(jiǎn)單定義及使用方法,需要的朋友可以參考下2018-02-02
js+canvas實(shí)現(xiàn)動(dòng)態(tài)吃豆人效果
本文主要介紹了js+canvas實(shí)現(xiàn)動(dòng)態(tài)吃豆人效果的實(shí)例。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03
SOSO地圖JS畫(huà)出標(biāo)注和中心點(diǎn)以html形式運(yùn)行
SOSO地圖想必大家都知道吧,本文將為大家詳細(xì)介紹下使用JS畫(huà)出標(biāo)注和中心點(diǎn),直接貼出代碼,感興趣的朋友可以參考下2013-08-08
通過(guò)js腳本復(fù)制網(wǎng)頁(yè)上的一個(gè)表格的不錯(cuò)實(shí)現(xiàn)方法
通過(guò)js腳本復(fù)制網(wǎng)頁(yè)上的一個(gè)表格的不錯(cuò)實(shí)現(xiàn)方法...2006-12-12

