成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

手把手和你用原生JS寫(xiě)一個(gè)循環(huán)播放圖片輪播

enda / 3717人閱讀

摘要:前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。作為演示,用標(biāo)簽代替了圖片。關(guān)鍵使用不同背景色的替代圖片。

前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。

先看看在線DEMO:原生JS循環(huán)播放圖片輪播組件?(支持IE8+,本文中的在線demo均未經(jīng)過(guò)壓縮,可以直接在瀏覽器中調(diào)試

以及GitHub倉(cāng)庫(kù)地址及完整代碼:JuniorTour/simple-standard-js-carousel

一、思路講解: 1.先說(shuō)基本的非循環(huán)無(wú)過(guò)渡圖片輪播:

這個(gè)思路還是很簡(jiǎn)單的,通過(guò)觀察一些圖片輪播就可以發(fā)現(xiàn),圖片輪播一般是以一個(gè)尺寸較小的父元素作為窗口,包裹住一組較長(zhǎng)的長(zhǎng)條狀的項(xiàng)目(item)子元素,再利用?overflow: hidden; ,將父元素作為“窗口”,只顯示出的項(xiàng)目子元素的一部分,并通過(guò)改變項(xiàng)目子元素的定位或translate3d屬性,實(shí)現(xiàn)多張圖片項(xiàng)目動(dòng)態(tài)播放。

基本原理可以參考這個(gè)demo:圖片輪播基本原理演示

2.比較有意思的其實(shí)是循環(huán)的功能:

但是這樣簡(jiǎn)單的輪播是不會(huì)循環(huán)播放的,也就是說(shuō)當(dāng)一輪圖片項(xiàng)目(item)播放到結(jié)尾;或者當(dāng)在第一張圖(第一個(gè)項(xiàng)目)繼續(xù)向前時(shí),就會(huì)超出內(nèi)容子元素,出現(xiàn)空白部分,這一般不是我們想要的結(jié)果。

有多種思路可以實(shí)現(xiàn)循環(huán)播放,我觀察到淘寶網(wǎng)首頁(yè)的圖片輪播是這樣的思路:

復(fù)制開(kāi)頭和結(jié)尾的項(xiàng)目,并分別放在開(kāi)頭和結(jié)尾,當(dāng)播放到開(kāi)頭或結(jié)尾的項(xiàng)目,繼續(xù)播放,需要循環(huán)時(shí),臨時(shí)取消transition屬性,并立即用定位跳轉(zhuǎn)至相應(yīng)的真正的開(kāi)頭或結(jié)尾之后,再恢復(fù)原來(lái)的transition,繼續(xù)正常滾動(dòng)播放,從而利用視覺(jué)上的“欺騙”,實(shí)現(xiàn)帶有過(guò)渡效果的循環(huán)播放。

相應(yīng)的原理可以參考這個(gè)demo:圖片輪播循環(huán)原理演示

二、HTML標(biāo)記部分

核心理念是簡(jiǎn)潔、語(yǔ)義化。這部分因?yàn)槲覍W(xué)過(guò)bootstrap框架所以借鑒了bootstrap的HTML標(biāo)記結(jié)構(gòu)。

整體結(jié)構(gòu)為:

外層的.carousel-wrapper包裹著輪播的三個(gè)主要部分,分別是:

.carousel-item-wrapper:項(xiàng)目?jī)?nèi)容部分(作為演示,本文中的demo使用a標(biāo)簽代替了圖片,大家可以自行嘗試替換為圖片;同時(shí)添加了文字序號(hào)標(biāo)記,以便于觀察理解,尤其要注意兩個(gè)復(fù)制的開(kāi)頭和結(jié)尾項(xiàng)目copy-1和copy-5)。

.carousel-control-wrapper:控制按鈕部分,即兩個(gè)用于控制左右移動(dòng)的按鈕。

.carousel-index-wrapper:索引按鈕部分,即圖片輪播中的那一排“小圓點(diǎn)”。為了便于用JS操控,我添加了id作為“鉤子”。而bootstrap在這里用的是自定義的data屬性。

三、CSS樣式部分

總的來(lái)說(shuō)比較簡(jiǎn)單,重要的地方我加上了注釋,有存疑的地方,歡迎和我交流。

    /*reset*/
    * {
        border: none;
        padding: 0;
        margin: 0;
    }
    button {
        outline: none;
    }
    li {
        list-style: none;
    }

    .carousel-wrapper {
        width:520px;
        height:280px;
        overflow: hidden;   /*關(guān)鍵*/
        position: relative;
        margin: 100px auto;
    }
    .carousel-item-wrapper {
        width:3640px;
        height:280px;
        position: absolute;
        top: 0;
        left: -520px;
        transition: left .2s ease-in;
    }
    .carousel-item a {
        display: block;
        background-color: red;
        width:520px;
        height: 280px;
    }

    /*使用不同背景色的a替代圖片。*/
    .carousel-item:nth-child(1) a {
        background-color: rgb(129,194,214);
        /*第五張圖片的復(fù)制*/
    }
    .carousel-item:nth-child(2) a {
        background-color: rgb(129,146,214);
    }
    .carousel-item:nth-child(3) a {
        background-color: rgb(217,179,230);
    }
    .carousel-item:nth-child(4) a {
        background-color: rgb(220,247,161);
    }
    .carousel-item:nth-child(5) a {
        background-color: rgb(131,252,216);
    }
    .carousel-item:nth-child(6) a {
        background-color: rgb(129,194,214);
    }
    .carousel-item:nth-child(7) a {
        background-color: rgb(129,146,214);
        /*第一張圖片的復(fù)制*/
    }

    .carousel-item {
        float: left;
    }
    .carousel-index-mark {
        font-size:60px;
        color: black;
        position: absolute;
        top: 0;
    }
    .carousel-control-wrapper {
        transition: all .2s;
    }
    .carousel-wrapper:hover button {
        display: block;
    }
    .carousel-control-wrapper button {
        transition: all .2s linear;
        display: none;
        width:24px;
        height:36px;
        line-height:36px;
        background-color: rgba(0,0,0,.3);
        color: #fff;
        position: absolute;
        top: 50%;
        cursor: pointer;
    }
    button#prev {
        left:0;
    }
    button#next {
        right:0;
    }
    button i {
        font-size: 18px;
    }
    .carousel-index-wrapper {
        width:65px;
        height:13px;
        overflow: hidden;
        position: absolute;
        bottom:15px;
        left:50%;
        margin-left: -33px;
    }
    .carousel-index-btn {
        width:9px;
        height:9px;
        float: left;
        margin:2px;
        background-color: #b7b7b7;
        border-radius: 50%;
        text-indent: -999em;
        /*這個(gè)-999em的文字對(duì)齊聲明有助于增強(qiáng)可訪問(wèn)性。*/
        cursor: pointer;
    }
    .active-carousel-index-btn {
        background-color: #f44103;
    }
四、JS部分

這一塊是主要部分,內(nèi)容較多,因此我們逐步來(lái)實(shí)現(xiàn)各部分功能以便于理解。

0.功能和結(jié)構(gòu)分析:

根據(jù)最開(kāi)始的思路講解,我們把這個(gè)輪播的JavaScript功能大致分為以下4個(gè)部分:
1.左右滑動(dòng)按鈕功能
2.索引按鈕跳轉(zhuǎn)功能
3.自動(dòng)播放功能
4.循環(huán)播放功能。

我們來(lái)分別逐步實(shí)現(xiàn)。

1.實(shí)現(xiàn)左右滑動(dòng)按鈕功能:
function addLoadEvent(func) {
    var oldLoad = window.onload;
    if (typeof oldLoad != "function") {
        window.onload = func;
    } else {
        window.onload = function () {
            oldLoad();
            func();
        }
    }
}
//給文檔加載完成后的load事件綁定相應(yīng)的處理函數(shù):
addLoadEvent(preventDefaultAnchors);
addLoadEvent(carouselControl);

/*用一個(gè)對(duì)象把輪播組件的相關(guān)參數(shù)封裝起來(lái),優(yōu)點(diǎn)是靈活便于擴(kuò)展升級(jí);缺點(diǎn)是同時(shí)也增加了文件的體積。*/
var carouselInfo = {
    itemWidth: 520,
    trueItemNum: 5,
    itemNum: 7,
    totalWidth: 7 * 520
};

//阻止a標(biāo)簽?zāi)J(rèn)的點(diǎn)擊跳轉(zhuǎn)行為
function preventDefaultAnchors() {
    var allAnchors = document.querySelectorAll("a");

    for (var i = 0; i < allAnchors.length; i++) {
        allAnchors[i].addEventListener("click", function (e) {
            e.preventDefault();
        }, false);
    }
}

function carouselControl () {
    var prev = document.querySelector("#prev");
    var next = document.querySelector("#next");
    var carouselWrapper = document.querySelector(".carousel-wrapper");

    prev.onclick = function () {
        slide(-1);
    };
    next.onclick = function () {
        slide(1);
    };
}

function slide(slideItemNum) {
    var itemWrapper=document.querySelector(".carousel-item-wrapper");
    var currentLeftOffset=(itemWrapper.style.left)?parseInt(itemWrapper.style.left): 0,
        targetLeftOffset=currentLeftOffset-(slideItemNum*carouselInfo.itemWidth);

    itemWrapper.style.left=targetLeftOffset+"px";
}

第1步的demo:carousel-step-1

2.實(shí)現(xiàn)索引按鈕跳轉(zhuǎn)功能:
function carouselControl() {
    var prev = document.querySelector("#prev");
    var next = document.querySelector("#next");
    var carouselWrapper = document.querySelector(".carousel-wrapper");
    //添加索引按鈕的引用
    var indexBtns = document.querySelectorAll(".carousel-index-btn");

    //標(biāo)記當(dāng)前所在的圖片編號(hào),用于配合控制.index-btn。
    var currentItemNum = 1;
    prev.onclick = function () {
        //把滑動(dòng)功能和切換索引按鈕功能裝入一個(gè)函數(shù)之中,以便于獲取當(dāng)前索引:
        currentItemNum=prevItem(currentItemNum);
    };
    next.onclick = function () {
        //把滑動(dòng)功能和切換索引按鈕功能裝入一個(gè)函數(shù)之中,以便于獲取當(dāng)前索引:
        currentItemNum=nextItem(currentItemNum);
    };

    for (var i = 0; i < indexBtns.length; i++) {
        //利用立即調(diào)用函數(shù),解決閉包的副作用,傳入相應(yīng)的index值
        (function (i) {
            indexBtns[i].onclick = function () {
                slideTo(i+1);
                currentItemNum=i+1;
            }
        })(i);
    }
}

function nextItem(currentItemNum) {
    slide(1);
    currentItemNum += 1;
    if (currentItemNum == 6) currentItemNum = 1;
    switchIndexBtn(currentItemNum);

    return currentItemNum;
}

function prevItem(currentItemNum) {
    slide(-1);
    currentItemNum -= 1;
    if (currentItemNum == 0) currentItemNum = 5;
    switchIndexBtn(currentItemNum);

    return currentItemNum;
}

//添加直接跳轉(zhuǎn)函數(shù):
function slideTo(targetNum) {
    var itemWrapper=document.querySelector(".carousel-item-wrapper");
    itemWrapper.style.left=-(targetNum*carouselInfo.itemWidth)+"px";
    switchIndexBtn(targetNum);
}

function slide(slideItemNum) {
    var itemWrapper = document.querySelector(".carousel-item-wrapper");
    var currentLeftOffset = (itemWrapper.style.left) ? parseInt(itemWrapper.style.left) : 0,
        targetLeftOffset = currentLeftOffset - (slideItemNum * carouselInfo.itemWidth);

    itemWrapper.style.left = targetLeftOffset + "px";
}

function switchIndexBtn(targetNum) {
    //切換當(dāng)前的索引按鈕
    //刪除過(guò)去激活的.active-carousel-index-btn
    var activeBtn=document.querySelector(".active-carousel-index-btn");
    activeBtn.className=activeBtn.className.replace(" active-carousel-index-btn","");

    //添加新的激活索引按鈕
    var targetBtn=document.querySelectorAll(".carousel-index-btn")[targetNum-1];
    targetBtn.className+=" active-carousel-index-btn";
}

第2步的demo:carousel-step-2

3.實(shí)現(xiàn)自動(dòng)播放功能:
function carouselControl() {
    //省略前面重復(fù)的代碼......

    for (var i = 0; i < indexBtns.length; i++) {
        //利用立即調(diào)用函數(shù),解決閉包的副作用,傳入相應(yīng)的index值
        (function (i) {
            indexBtns[i].onclick = function () {
                slideTo(i+1);
                currentItemNum=i+1;
            }
        })(i);
    }

    //添加定時(shí)器
    var scrollTimer;
    function play() {
        scrollTimer=setInterval(function () {
            currentItemNum=nextItem(currentItemNum);
        },2000);
    }
    play();

    function stop() {
        clearInterval(scrollTimer);
    }

    //綁定事件
    carouselWrapper.addEventListener("mouseover",stop);
    carouselWrapper.addEventListener("mouseout",play,false);

    /*DOM二級(jí)的addEventListener相對(duì)于on+sth的優(yōu)點(diǎn)是:
     * 1.addEventListener可以先后添加多個(gè)事件,同時(shí)這些事件還不會(huì)相互覆蓋。
     * 2.addEventListener可以控制事件觸發(fā)階段,通過(guò)第三個(gè)可選的useCapture參數(shù)選擇冒泡還是捕獲。
     * 3.addEventListener對(duì)任何DOM元素都有效,而不僅僅是HTML元素。*/
}

第3步的demo:carousel-step-3

4.關(guān)鍵點(diǎn):實(shí)現(xiàn)循環(huán)播放功能:
function slide(slideItemNum) {
    var itemWrapper = document.querySelector(".carousel-item-wrapper");
    var currentLeftOffset = (itemWrapper.style.left) ? parseInt(itemWrapper.style.left) : 0,
        targetLeftOffset = currentLeftOffset - (slideItemNum * carouselInfo.itemWidth);

    /*不在這里跳轉(zhuǎn)了。先處理偏移值,實(shí)現(xiàn)循環(huán),再跳轉(zhuǎn)。*/
    //itemWrapper.style.left = targetLeftOffset + "px";

    switch (true) {
            /*switch 的語(yǔ)法是:當(dāng)case之中的表達(dá)式等于switch (val)的val時(shí),執(zhí)行后面的statement(語(yǔ)句)。*/
        case (targetLeftOffset>0):
            itemWrapper.style.transition="none";
            itemWrapper.style.left=-carouselInfo.trueItemNum*carouselInfo.itemWidth+"px";
            /*此處即相當(dāng)于:itemWrapper.style.left="-2600px";*/
            targetLeftOffset=-(carouselInfo.trueItemNum-1)*carouselInfo.itemWidth;
            //相當(dāng)于:targetLeftOffset=-2080;
            break;
        case (targetLeftOffset<-(carouselInfo.totalWidth-carouselInfo.itemWidth)):
            //此處即相當(dāng)于:targetLeftOffset<-3120
            itemWrapper.style.transition="none";
            itemWrapper.style.left=-carouselInfo.itemWidth+"px";
            //相當(dāng)于:itemWrapper.style.left="-520px";
            targetLeftOffset=-carouselInfo.itemWidth*2;
            //相當(dāng)于:targetLeftOffset=-1040;
            break;
    }

    /*這里我使用了setTimeout(fn,0)的hack
     * 參考bootstrap的carousel.js源碼,似乎也利用了setTimeout(fn,0)這一hack。
     *
     * stackoverflow上有對(duì)這一hack的討論和解釋:
     * http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful
     * 根據(jù)第二個(gè)回答,我個(gè)人的理解是:setTimeout(fn,0)相當(dāng)于異步執(zhí)行內(nèi)部的代碼fn,
     * 具體到這個(gè)輪播,就是在上一輪非過(guò)渡定位的頁(yè)面渲染工作(switch語(yǔ)句內(nèi)部的case)結(jié)束之后,再執(zhí)行setTimeout內(nèi)部的過(guò)渡位移工作。
     * 從而避免了,非過(guò)渡的定位還未結(jié)束,就恢復(fù)了過(guò)渡屬性,使得這一次非過(guò)渡的定位也帶有過(guò)渡效果。
     **/

    //各位可以試一試,把setTimeout內(nèi)部的代碼放在外部,“循環(huán)”時(shí)會(huì)有什么樣的錯(cuò)誤效果。
    //itemWrapper.style.transition="left .2s ease-in";
    //itemWrapper.style.left=targetLeftOffset+"px";

    setTimeout(function () {
        itemWrapper.style.transition="left .2s ease-in";
        itemWrapper.style.left=targetLeftOffset+"px";
    },20);
}

第4步的demo:carousel-step-4

至此,就完成了一個(gè)完整的循環(huán)播放圖片輪播,欣賞一下自己的杰作吧~~~ヾ(??▽?)ノ

五、源碼及示例: 1.GitHub倉(cāng)庫(kù)地址及完整代碼:JuniorTour/simple-standard-js-carousel 2.在線demo:原生JS循環(huán)播放圖片輪播組件?

很慚愧,只做了一點(diǎn)簡(jiǎn)單的工作。如果覺(jué)得本文不錯(cuò)的話,歡迎給我的GitHub點(diǎn)贊!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83417.html

相關(guān)文章

  • 把手你用原生JS寫(xiě)一個(gè)循環(huán)播放圖片輪播

    摘要:前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。作為演示,用標(biāo)簽代替了圖片。關(guān)鍵使用不同背景色的替代圖片。 前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。 先看看在線DEMO:原生JS循環(huán)播放圖片輪播組件?(支持IE8+,本文中的在線demo均未經(jīng)過(guò)壓縮...

    dendoink 評(píng)論0 收藏0
  • 把手你用原生JS寫(xiě)一個(gè)循環(huán)播放圖片輪播

    摘要:前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。作為演示,用標(biāo)簽代替了圖片。關(guān)鍵使用不同背景色的替代圖片。 前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。 先看看在線DEMO:原生JS循環(huán)播放圖片輪播組件?(支持IE8+,本文中的在線demo均未經(jīng)過(guò)壓縮...

    gityuan 評(píng)論0 收藏0
  • 把手你用原生JavaScript造輪子(2)——輪播圖(更新:ES6版本)

    摘要:綁定輪播事件然后是鼠標(biāo)移入移出事件的綁定鼠標(biāo)移入移出事件移入時(shí)停止輪播播放的定時(shí)器,移出后自動(dòng)開(kāi)始下一張的播放。 通過(guò)上一篇文章的學(xué)習(xí),我們基本掌握了一個(gè)輪子的封裝和開(kāi)發(fā)流程。那么這次將帶大家開(kāi)發(fā)一個(gè)更有難度的項(xiàng)目——輪播圖,希望能進(jìn)一步加深大家對(duì)于面向?qū)ο蟛寮_(kāi)發(fā)的理解和認(rèn)識(shí)。 So, Lets begin! 目前項(xiàng)目使用 ES5及UMD 規(guī)范封裝,所以在前端暫時(shí)只支持標(biāo)簽的引入方式...

    jasperyang 評(píng)論0 收藏0
  • 最簡(jiǎn)單的無(wú)縫輪播

    摘要:昨天學(xué)習(xí)了輪播的原理,今天再來(lái)看看無(wú)縫輪播的技術(shù)。無(wú)縫輪播無(wú)縫輪播的原來(lái)大致類似小時(shí)候跳大繩,小朋友一個(gè)個(gè)進(jìn)入,一個(gè)個(gè)出來(lái),出來(lái)后排到隊(duì)伍末尾,等在著進(jìn)入,無(wú)縫輪播也類似這種機(jī)制。 昨天學(xué)習(xí)了輪播的原理,今天再來(lái)看看無(wú)縫輪播的技術(shù)。 昨天學(xué)習(xí)的輪播機(jī)制類似于走馬燈,所有圖片排成一排,輪流在你眼前走過(guò),你就會(huì)感覺(jué)他們動(dòng)起來(lái)了,今天學(xué)的無(wú)縫輪播就不能用昨天的思路了,它和昨天最大的區(qū)別是,從...

    Kyxy 評(píng)論0 收藏0
  • 授人以漁式解析原生JS寫(xiě)輪播

    摘要:鼠標(biāo)放到輪播圖的圖片上時(shí)不再自動(dòng)輪播并且左右箭頭顯示出來(lái),鼠標(biāo)移開(kāi)時(shí)左右箭頭隱藏掉并且自動(dòng)輪播。核心原理清除定時(shí)器,綁定事件,重構(gòu)下代碼封裝出往右往左輪播函數(shù)和自動(dòng)輪播函數(shù)。 需求與分析 需求:循環(huán)無(wú)縫自動(dòng)輪播五張圖,按左右箭頭可以手動(dòng)切換圖片,鼠標(biāo)點(diǎn)擊輪播圖下面按鈕 1 2 3 4 5會(huì)跳轉(zhuǎn)到對(duì)應(yīng)的第1 2 3 4 5張圖片。鼠標(biāo)放到輪播圖的圖片上時(shí)不再自動(dòng)輪播并且左右箭頭顯示出來(lái),...

    Zack 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<