js原生—— 無縫輪播

今天分享前端開發(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>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末间学,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子印荔,更是在濱河造成了極大的恐慌低葫,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仍律,死亡現(xiàn)場離奇詭異嘿悬,居然都是意外死亡,警方通過查閱死者的電腦和手機水泉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門善涨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人草则,你說我怎么就攤上這事钢拧。” “怎么了畔师?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵娶靡,是天一觀的道長。 經(jīng)常有香客問我看锉,道長姿锭,這世上最難降的妖魔是什么塔鳍? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮呻此,結(jié)果婚禮上轮纫,老公的妹妹穿的比我還像新娘。我一直安慰自己焚鲜,他們只是感情好掌唾,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著忿磅,像睡著了一般糯彬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上葱她,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天撩扒,我揣著相機與錄音,去河邊找鬼吨些。 笑死搓谆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的豪墅。 我是一名探鬼主播泉手,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼偶器!你這毒婦竟也來了斩萌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤状囱,失蹤者是張志新(化名)和其女友劉穎术裸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亭枷,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年搀崭,在試婚紗的時候發(fā)現(xiàn)自己被綠了叨粘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘤睹,死狀恐怖升敲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轰传,我是刑警寧澤驴党,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站获茬,受9級特大地震影響港庄,放射性物質(zhì)發(fā)生泄漏倔既。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一鹏氧、第九天 我趴在偏房一處隱蔽的房頂上張望渤涌。 院中可真熱鬧,春花似錦把还、人聲如沸实蓬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至艇炎,卻和暖如春酌伊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冕臭。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工腺晾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辜贵。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓悯蝉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親托慨。 傳聞我的和親對象是個殘疾皇子鼻由,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容