30_用js實現一個輪播圖效果,簡單說下原理

一、原理

將一些圖片在一行中平鋪,然后計算偏移量再利用定時器實現定時輪播。

步驟一:建立html基本布局

如下所示:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>輪播圖</title>
</head>
<body>
    <div class="container">
        <div class="wrap" style="left:-600px;">
            <img src="./img/5.jpg" alt="">
            <img src="./img/1.jpg" alt="">
            <img src="./img/2.jpg" alt="">
            <img src="./img/3.jpg" alt="">
            <img src="./img/4.jpg" alt="">
            <img src="./img/5.jpg" alt="">
            <img src="./img/1.jpg" alt="">
        </div>
        <div class="buttons">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
            <span>5</span>
        </div>
        <a href="javascript:;" class="arrow arrow_left">&lt;</a>
        <a href="javascript:;" class="arrow arrow_right">&gt;</a>
    </div>
</body>
</html>

只有五張圖片,卻使用7張來輪播,這是為了實現無縫輪播,后面會詳細介紹。

而5個span,即我們可以實時看到輪播圖目前所處的位置。

最后是兩個按鈕,可以通過它來控制前進與后退。

這里我們需要對wrap使用絕對定位,所以用left:-600px;將第一張圖片顯示出來。

步驟二: css布局

首先,reset css,如下所示:

* {
    margin: 0;
    padding: 0;
}
a {
    text-decoration: none;
}

接著,我們為了讓圖片只在container中,所以需要限定其寬度和高度并且使用overflow:hidden;將其余的圖片隱藏起來,并且我們希望wrap相對于container左右移動,所以設置為relative,如下:

.container {
    position: relative;
    width: 600px;
    height: 400px;
    margin:100px auto 0 auto;
    box-shadow: 0 0 5px green;
    overflow: hidden;
}

我們設置wrap是絕對定位的,所以我們就可以通過控制Left和Right來控制圖片的移動了。設置z-index:1;以對后面將要放置的buttons作為參考。 因為共有七張圖片,所以width為4200px(每張圖片我們設置為600X400),我們只需讓圖片左浮動即可實現占滿一排了。

.wrap {
    position: absolute;
    width: 4200px;
    height: 400px;
    z-index: 1;
}

然后我們把圖片設置為左浮動,并限定其大小,如下所示:

.container .wrap img {
    float: left;
    width: 600px;
    height: 400px;
}

即這時已經顯示出了第一張圖片。并且充滿了整個container(container是有box-shadow的);

然后我們把顯示次序的buttons放在圖片的右下角。并且設置z-index:2;以保證buttons是在圖片的上面的。

.container .buttons {
    position: absolute;
    right: 150px;
    bottom:20px;
    width: 100px;
    height: 10px;
    z-index: 2;
}

然后將buttons下面的span做一個簡單的修飾,并且給和圖片對應的span設置一個on類,如下:

.container .buttons span {
    margin-left: 5px;
    display: inline-block;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: green;
    text-align: center;
    color:white;
    cursor: pointer;
}
.container .buttons span.on{
    background-color: red;
}

接下來,我們把左右切換的箭頭加上,然后做簡單的修飾,注意:因為這里使用實體來表示左右箭頭,所以設置font-size才能改變其大小

.container .arrow {
    position: absolute;
    top: 35%;
    color: green;
    padding:0px 14px;
    border-radius: 50%;
    font-size: 50px;
    z-index: 2;
    display: none;
}
.container .arrow_left {
    left: 10px;
}
.container .arrow_right {
    right: 10px;
}
.container:hover .arrow {
    display: block;
}
.container .arrow:hover {
    background-color: rgba(0,0,0,0.2);
}

步驟三:添加js邏輯

我們首先獲取到 wrap(因為要設置其left才能控制輪播圖),然后獲取到左右兩個箭頭,并實現手動輪播,如下:

var wrap = document.querySelector(".wrap");
var next = document.querySelector(".arrow_right");
var prev = document.querySelector(".arrow_left");
next.onclick = function () {
    next_pic();
}
prev.onclick = function () {
    prev_pic();
}
function next_pic () {
    var newLeft = parseInt(wrap.style.left)-600;
    wrap.style.left = newLeft + "px";
}
function prev_pic () {
    var newLeft = parseInt(wrap.style.left)+600;
    wrap.style.left = newLeft + "px";
}

值得注意的是,這里wrap.style.left是一個字符串,所以要轉化為數字才能進行計算,而設定left時就要加上px成為一個字符串了。

在第一頁時,left值為-600,所以我們可以點擊一次上一張,但是當再點擊一次時,就出現了空白。同樣的,下一張點擊,到-3600是最后一張,就不能再繼續點擊了。

也就是說,當我們點擊下一張到-3600px(這是第一張圖片)時,我們需要下次跳轉到第二張,即-1200px;這樣才能正常跳轉;

同理,當我們點擊上一張到0px(這是第五張圖片時),我們希望下次跳轉到第四張,即-2400px;

按照這樣的思路我們重新將next_pic和prev_pic函數修改如下:

function next_pic () {
    var newLeft;
    if(wrap.style.left === "-3600px"){
        newLeft = -1200;
    }else{
        newLeft = parseInt(wrap.style.left)-600;
    }
    wrap.style.left = newLeft + "px";
}
function prev_pic () {
    var newLeft;
    if(wrap.style.left === "0px"){
        newLeft = -2400;
    }else{
        newLeft = parseInt(wrap.style.left)+600;
    }
    wrap.style.left = newLeft + "px";
}

這時,我們就可以發現圖片可以循環播放了!

但是,這時我們僅僅是手動循環播放的,我們如果希望自動播放,使用setInterval()即可,如下所示:

var timer = null;
function autoPlay () {
    timer = setInterval(function () {
        next_pic();
    },1000);
}
autoPlay();

即先設定一個計時器,然后創建一個可以自動播放的函數,最后調用這個函數即可。 現在它就可以自動播放了。

但是如果我們想要仔細看其中一個圖片的時候,我們希望輪播圖停止播放,只要clearInterval()即可,如下:

var container = document.querySelector(".container");
container.onmouseenter = function () {
    clearInterval(timer);
}
container.onmouseleave = function () {
    autoPlay();    
}

現在,只要我們把鼠標移入輪播圖中,這時輪播圖就不會播放了。而移開鼠標之后,輪播圖自動播放。

但是到目前為止,輪播圖下方的小圓點還沒有動,現在我們就實現它。

原理很簡單,即設置buttons的index初始值為0,即第一個span的class為on,然后觸發next_pic函數時,index加1,當觸發prev_pic函數時,index減1, 并設置當前index的小圓點的class為on, 這就要求index必須設置為全局變量,才能保證它在每一個函數的作用域中。

添加showCurrentDot函數:

var index = 0;
var dots = document.getElementsByTagName("span");
function showCurrentDot () {
    for(var i = 0, len = dots.length; i < len; i++){
        dots[i].className = "";
    }
    dots[index].className = "on";
}

在next_pic中添加代碼:

index++;
if(index > 4){
    index = 0;
}

在prev_pic中添加代碼:

index--;
if(index < 0){
    index = 4;
}
showCurrentDot();

這樣,輪播圖就可以自動切換,并且小圓點也在隨著圖片的變化而變化了。

但是,這距離我們經常看到的輪播圖還有一定距離 - - - 當點擊小圓點時, 就可跳轉到相應圖片。 實現原理即: 點擊小圓點,就使wrap的Left變成相應的值。代碼如下:

for (var i = 0, len = dots.length; i < len; i++){
    (function(i){
        dots[i].onclick = function () {
            var dis = index - i;
            if(index == 4 && parseInt(wrap.style.left)!==-3000){
                dis = dis - 5;     
            }
            //和使用prev和next相同,在最開始的照片5和最終的照片1在使用時會出現問題,導致符號和位數的出錯,做相應地處理即可
            if(index == 0 && parseInt(wrap.style.left)!== -600){
                dis = 5 + dis;
            }
            wrap.style.left = (parseInt(wrap.style.left) +  dis * 600)+"px";
            index = i;
            showCurrentDot();
        }
    })(i);            
}

原理就是當點擊到小圓點時,得到相應的i值,這個i值也就是span的index值,我們拿他和全局變量index作比較,然后重新設置wrap.style.left的值,然后把i值復制給全局變量index,最后顯示當前的小原點即可。值得注意的是:這里涉及到了閉包的概念,如果直接使用for循環,則不能得到正確的結果。

最終效果圖如下:

最終代碼如下所示:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>輪播圖</title>
<style>
    * {
        margin:0;
        padding:0;
    }
    a{
        text-decoration: none;
    }
    .container {
        position: relative;
        width: 600px;
        height: 400px;
        margin:100px auto 0 auto;
        box-shadow: 0 0 5px green;
        overflow: hidden;
    }
    .container .wrap {
        position: absolute;
        width: 4200px;
        height: 400px;
        z-index: 1;
    }
    .container .wrap img {
        float: left;
        width: 600px;
        height: 400px;
    }
    .container .buttons {
        position: absolute;
        right: 5px;
        bottom:40px;
        width: 150px;
        height: 10px;
        z-index: 2;
    }
    .container .buttons span {
        margin-left: 5px;
        display: inline-block;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background-color: green;
        text-align: center;
        color:white;
        cursor: pointer;
    }
    .container .buttons span.on{
        background-color: red;
    }
    .container .arrow {
        position: absolute;
        top: 35%;
        color: green;
        padding:0px 14px;
        border-radius: 50%;
        font-size: 50px;
        z-index: 2;
        display: none;
    }
    .container .arrow_left {
        left: 10px;
    }
    .container .arrow_right {
        right: 10px;
    }
    .container:hover .arrow {
        display: block;
    }
    .container .arrow:hover {
        background-color: rgba(0,0,0,0.2);
    }
</style>
</head>
<body>
<div class="container">
    <div class="wrap" style="left: -600px;">
        <img src="./img/5.jpg" alt="">
        <img src="./img/1.jpg" alt="">
        <img src="./img/2.jpg" alt="">
        <img src="./img/3.jpg" alt="">
        <img src="./img/4.jpg" alt="">
        <img src="./img/5.jpg" alt="">
        <img src="./img/1.jpg" alt="">
    </div>
    <div class="buttons">
        <span class="on">1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
    </div>
    <a href="javascript:;" class="arrow arrow_left">&lt;</a>
    <a href="javascript:;" class="arrow arrow_right">&gt;</a>
</div>
<script>
    var wrap = document.querySelector(".wrap");
    var next = document.querySelector(".arrow_right");
    var prev = document.querySelector(".arrow_left");
    next.onclick = function () {
        next_pic();
    }
    prev.onclick = function () {
        prev_pic();
    }
    function next_pic () {
        index++;
        if(index > 4){
            index = 0;
        }
        showCurrentDot();
        var newLeft;
        if(wrap.style.left === "-3600px"){
            newLeft = -1200;
        }else{
            newLeft = parseInt(wrap.style.left)-600;
        }
        wrap.style.left = newLeft + "px";
    }
    function prev_pic () {
        index--;
        if(index < 0){
            index = 4;
        }
        showCurrentDot();
        var newLeft;
        if(wrap.style.left === "0px"){
            newLeft = -2400;
        }else{
            newLeft = parseInt(wrap.style.left)+600;
        }
        wrap.style.left = newLeft + "px";
    }
    var timer = null;
    function autoPlay () {
        timer = setInterval(function () {
            next_pic();
        },2000);
    }
    autoPlay();

    var container = document.querySelector(".container");
    container.onmouseenter = function () {
        clearInterval(timer);
    }
    container.onmouseleave = function () {
        autoPlay();    
    }

    var index = 0;
    var dots = document.getElementsByTagName("span");
    function showCurrentDot () {
        for(var i = 0, len = dots.length; i < len; i++){
            dots[i].className = "";
        }
        dots[index].className = "on";
    }

    for (var i = 0, len = dots.length; i < len; i++){
        (function(i){
            dots[i].onclick = function () {
                var dis = index - i;
                if(index == 4 && parseInt(wrap.style.left)!==-3000){
                    dis = dis - 5;     
                }
                //和使用prev和next相同,在最開始的照片5和最終的照片1在使用時會出現問題,導致符號和位數的出錯,做相應地處理即可
                if(index == 0 && parseInt(wrap.style.left)!== -600){
                    dis = 5 + dis;
                }
                wrap.style.left = (parseInt(wrap.style.left) +  dis * 600)+"px";
                index = i;
                showCurrentDot();
            }
        })(i);            
    }
</script>
</body>
</html>

二、總結

實現一個輪播圖還是不難的,大體思路: 先創建一個div,限定其寬度和高度,overflow:hidden,且設置其position為relative。然后創建一個裝圖片的div,寬度為所有圖片的總寬度,且設置其position為absolute,并且使其中的內容浮動,這樣所有的圖片就處于一行中。然后為了實現無縫滾動,所以需要在首尾分別添加一張過渡圖片。 先添加兩個按鈕, 使其可以手動輪播,然后只需要添加一個定時器使其朝一個方向自動輪播即可,因為用戶有時需要查看詳情,所以當鼠標進入時就clear定時器,滑出再定時播放。為了更好地用戶體驗,我們在下面添加了一排小圓點,用戶可以清楚地知道現在所處的位置, 最后, 利用閉包使得用戶可以直接通過點擊小圓點切換圖片。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容

  • 輪播圖感悟:1、通過b站的介紹寫出了沒有計時器的輪播圖(有很多種方法)2、具體的過程是這樣的:1、首先通過一個表單...
    想和于謙共枕眠閱讀 399評論 0 0
  • 進入前端將近一年了,js還是很弱,突發奇想寫一個輪播圖,就找到了這個博主的材料,和大家分享。 輪播圖的原理: 一系...
    FRRRR閱讀 3,677評論 0 11
  • 原理 圖片輪播原理:將一系列大小相等的圖片平鋪,利用css布局只顯示一張圖片,其他圖片隱藏,通過計算偏移量利用定時...
    黎貝卡beka閱讀 2,273評論 1 2
  • 輪播呢,也是各種網站上常見的一種展示效果,這里我來寫一寫實現輪播的一些簡單方法。//不知道為什么系統吃了代碼里面的...
    zkhChris閱讀 35,683評論 3 140
  • 0.最終效果預覽 基本功能 自動無縫滾動 左右按鈕控制滾動 點擊圓點切換圖片 1.整體結構與思路 Html部分 三...
    拾實閱讀 67,945評論 9 57