1. 程式人生 > >js原生實現輪播圖效果(面向對象編程)

js原生實現輪播圖效果(面向對象編程)

alt 狀態 off wid 編程) .proto eat doc 持續時間

面向對象編程js原生實現輪播圖效果

1.先看效果圖

技術分享圖片

2.需要實現的功能:

  • 自動輪播
  • 點擊左右箭頭按鈕無縫輪播
  • 點擊數字按鈕切換圖片

分析:如何實現無縫輪播?
在一個固定大小的相框裏有一個ul標簽,其長度是幾個圖片寬度的總和,通過translateX()的方法來實現左右移動動畫。
如何實現無縫呢?比如有三張圖片,可以在把第一張圖片通過cloneNode的方法克隆下來放到第三張圖片後面。圖片順序 1,2,3,1,看下面的HTML結構,結構中並沒有4張圖,第四張圖是生成的。

3.html結構

<!-- ul是圖片盒子,ol是數字按鈕盒子,最下面的div是左右箭頭按鈕盒子 -->
<div class="container">
    <div id="screen">
        <ul>
            <li><img src="./img/1.jpg" alt=""></li>
            <li><img src="./img/2.jpg" alt=""></li>
            <li><img src="./img/3.jpg" alt=""></li>
        </ul>
        <ol>
            <!--<li class="active">1</li>-->
            <!--<li>2</li>-->
            <!--<li>3</li>-->
        </ol>
    </div>
    <div>
        <span>&lt;</span>
        <span>&gt;</span>
    </div>
</div>

4.功能實現

4.1 創建對象

創建一個對象,需要傳入一個相框盒子元素,通過這個元素來獲取盒子中其他需要的元素,並把這些作為這個Carousel對象的屬性:

function Carousel(el) {
    this.screen = el; // 相框
    this.width = this.screen.offsetWidth; // 相框寬度
    this.ulBox = this.screen.children[0]; // ul盒子
    this.list = this.ulBox.children; // ul下面所有li
    this.olBox = this.screen.children[1]; // 數字按鈕盒子
    this.arrow = this.screen.nextElementSibling; // 箭頭盒子
    this.leftArraw = this.arrow.children[0]; // 左箭頭
    this.rightArraw = this.arrow.children[1]; // 右箭頭
    this.index = 0; // 數字按鈕的索引
    this.timeId = null; // 定時器的id
    this.activeClass = 'active'; // 數字按鈕class名
    this.durtion = '.35s'; // 動畫持續時間
}

4.2動畫效果由translateX實現

// 動畫
Carousel.prototype.animate = function (target) {
    this.ulBox.style.transform = 'translateX(' + target + 'px)'
};

4.3根據輪播圖片個數生成數字按鈕節點

生成節點後,為新生成的節點添加點擊事件,實現每次點擊根據節點對應的index切換圖片,這裏實現的需求的第三個功能。

// 創建節點
Carousel.prototype.createNodes = function () {
    let self = this;
    // 創建按鈕節點
    for (let i = 0; i < self.list.length; i++) {
        let liObj = document.createElement('li');
        liObj.innerText = i + 1;
        self.olBox.appendChild(liObj);
    
        // 為生成的數字按鈕添加點擊事件
        liObj.onclick = function () {
            self.index = this.innerText - 1; // 獲取當前點擊對象的索引值
            self.switch_sel();
            self.animate(-self.index * self.width);
        };
    }
    // 默認顯示第一張圖片,第一個數字按鈕默認選中狀態
    self.olBox.children[0].className = self.activeClass;
    // 克隆第一張圖放到ulBox後面,實現無縫輪播
    self.ulBox.appendChild(self.ulBox.children[0].cloneNode(true));
};

4.4輪播圖數字按鈕點擊切換狀態

因為多次用到這段代碼,所有就寫成一個方法掛在Carousel對象上了

// 切換數字按鈕的選中狀態
Carousel.prototype.switch_sel = function(){
    let self = this;
    for (let i = 0; i < self.olBox.children.length; i++) {
        self.olBox.children[i].removeAttribute('class');
    }
    self.olBox.children[self.index].className = self.activeClass;
};

4.5輪播事件,也是點擊右箭頭的事件

// 輪播事件
Carousel.prototype.clickHandle = function () {
    let self = this;
    // 如果是最後一張圖,直接跳到第一張
    if (self.index === self.list.length - 1) {
        self.index = 0;

        // 當點擊到最後一張時直接跳到第一張
        self.ulBox.style.transitionDuration = '0s';
        self.animate(-self.index * self.width);
    }

    // 必須有時間延遲,否則圖片跳轉切換不成功,因為self.animate()沒有來得及執行就被後面的self.animate()函數覆蓋了。
    setTimeout(function () {
        self.ulBox.style.transitionDuration = self.durtion;
        self.index++;
        self.animate(-self.index * self.width);

        // 如果是最後一張圖,則去掉最後一個的class屬性,切換到第一個
        if (self.index === self.list.length - 1) {
            self.olBox.children[self.olBox.children.length - 1].removeAttribute('class');
            self.olBox.children[0].className = self.activeClass;
        } else { // 切換當前選中狀態
            self.switch_sel();
        }
    }, 20);
};

4.6事件綁定

為左右箭頭點擊綁定事件,同時當鼠標hover在相框上時自動輪播取消,鼠標離開相框時自動輪播開始執行。

// 事件綁定
Carousel.prototype.bindEvent = function () {
    let self = this;
    // 又點擊下一張
    self.rightArraw.onclick = function () {
        self.clickHandle();
    };
    // 左點擊上一張
    self.leftArraw.onclick = function(){
        if(self.index === 0){
            self.index = self.list.length - 1;

            // 直接跳到最後一張
            self.ulBox.style.transitionDuration = '0s';
            self.animate(-self.index * self.width);
        }

        setTimeout(function(){
            self.ulBox.style.transitionDuration = self.durtion;
            self.index--;
            self.animate(-self.index * self.width);
            self.switch_sel();
        }, 20);
    };

    // 鼠標懸停清除定時器
    self.screen.parentElement.onmouseover = function(){
        self.timeId && clearInterval(self.timeId);
        self.arrow.style.display = 'flex';

    };
    // 鼠標離開打開定時器
    self.screen.parentElement.onmouseout = function(){
        self.timeId = setInterval(self.clickHandle.bind(self), 2000);
        self.arrow.style.display = 'none';
    }
};

4.7初始化方法

初始化方法中創建節點,綁定事件,同時設定定時器實現自動輪播效果。

// 初始化
Carousel.prototype.init = function () {
    this.createNodes();
    this.bindEvent();
    this.timeId = setInterval(this.clickHandle.bind(this), 2000);
    // 註意這裏要bind(this) 否則clickHandle中的this指向window
};

4.8實例化Carousel對象,大功告成

實例化一個輪播圖對象,然後調該對象的init方法。
只要html結構相同,只需要傳入不同的相框元素,就可以在同一個頁面中實例化多個輪播圖對象。也就是說,同一個頁面的多處輪播效果。

let carousel = new Carousel(document.getElementById('screen'));
carousel.init();

5備註

全部的代碼和css樣式可參考我的github中的輪播圖倉庫,菜鳥程序猿一枚,程序設計如果有不妥的地方歡迎提出意見或建議,當然啦,如果你喜歡並star了我的這個倉庫,我會很開心的 : )
[1]: https://github.com/jiangleiundo/carousel

js原生實現輪播圖效果(面向對象編程)