當前位置:網站首頁>原生JS 實現輪播圖效果

原生JS 實現輪播圖效果

2022-05-14 12:36:22美劇之神

原生JS

原生態JS是指遵循ECMAScript標准的javascript,在不使用框架的情况下考察我們對於對JS語法的了解和API的掌握。雖然目前大都是根據框架來進行前端的編程,但對於原生JS的掌握還是很重要的吧,本代碼實現的效果如下:

效果見原文

根據傳入的圖片數量在頁面的底部呈現輪播圖的圖片數量和當前為第幾張圖片,點擊相應的圓圈則可以跳轉至其他圖片;左右兩個按鈕同樣可以實現圖片的切換,如果當前為第一張或者最後一張圖片,點擊左移或者右移按鈕即可完成循環操作,從第一張圖片跳轉至最後一張圖片,且切換圖片的效果還在。具體的實現如下:

思路闡述

HTML部分

既然說是原生JS實現,那麼html和CSS我們能少用就少用。整個html內,僅寫入一個div,其CSS格式錶示其鋪滿整個屏幕,引入額外寫的index.js後,在body下新建一個Slider對象,並插入我們要輪播的圖片。整體代碼僅此而已,其詳細代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>last experiment</title>
    <script src="index.js"></script>
</head>
<body>
    <div style="
                position: fixed;
                top:0px;
                bottom: 0px;
                left: 0px;
                right: 0px;
                background-color: #333;">
    </div>
</body>
<script>
    new Slider(
        document.querySelector('div'),
        [
            'images/1.png',
            'images/3.jpg',
            'images/25.png'
        ]
    )
</script>
</html>

JS部分

我的思路是將所有圖片加載在一個div中,我們稱該div之為innerct,該div采取fixed布局,讓圖片在一整行內顯示,每個圖片與該div的大小一致。根據該div平移的距離即可實現頁面呈現的圖片的切換,同時帶平移效果。

思路實現的目標就是下圖第一行的內容,紅框錶示當前展示的圖片,如現在頁面展示的就是編號為 Ⅱ 的圖片。但是假如當前圖片為第一張,同時我又按下了左移按鈕,根據輪播圖的特性,我應該跳轉至圖片三,同時頁面呈現出圖片向右滑動,即左移的效果,呈現出編號為 Ⅲ 的圖片。

為了實現這個效果,那麼innerct內的圖片排列應該是下圖第二行的這種情况。同時,當頁面呈現的圖片為第二行的第一個 編號為 Ⅲ 時,將此時的第二行的第一個 Ⅲ 瞬移至 第二行的第四個圖片 Ⅲ 。同理,當頁面呈現第二行的第五個圖片 Ⅰ 時,再將圖片瞬移至第二行的第二個 Ⅰ 圖片即可不露聲色的完成輪播圖的效果實現。那麼此時我們需要解决的就是如何實現“瞬移“操作。

圖片的平移效果我們采取了CSS樣式中的過渡效果,那我們將平移的過程設置在在1s內完成,就可以展示出平移的過程,而頁面不會呈現出圖片的瞬間切換。根據這個平移的實現思路,我們就可以設置當頁面呈現的圖片為第二行的第一個Ⅲ 和 第五個 Ⅰ時,將平移的過程設置在0s完成,將圖片瞬移至第二行的第四個 Ⅲ 和 第二行的第二個 Ⅰ。其他比特置時,平移過程的過渡效果再次恢複為1s內完成即可。

代碼實現

根據以上的思路,我們就可以進行JS的編程了。代碼分為兩部分一個是Slider類,來實現輪播圖對象;一個是工具函數來實現异步睡眠操作。由於前端的知識點比較雜糅,具體的講解,我在代碼中進行注釋來一一說明,下面我們開始 >灬<。

class Slider {
    constructor(ct, imgs) { //該類傳入的參數為一個dom元素和要輪播圖片的list

        this.currentPage = 0; //當前頁面展示的圖片下標
        this.pageCount = imgs.length; //輪播圖的數量 aka,圖片list的 大小
        // let width = window.innerWidth;//全屏
        let width = ct.offsetWidth; //此處實現的是讓圖片全屏顯示,使用上面的語句也可以實現,但由於本次html中只有一個div,用該div的外輪廓寬也是可以的。
        this.width = width;
        let height = ct.offsetHeight;

        this.innerCt = document.createElement('div');
        this.innerCt.style.cssText = `width: ${width * (imgs.length + 2)}px;//設置圖片所在div的寬度,其寬度為 圖片的數據 + 首部的最後一張圖片 和 尾部的第一張圖片,aka,圖片list的長度 + 2。
        height:100%;padding:0;margin:0;transition:transform 1s ease;left:0`;//設置transition 過渡效果,平移 持續時間為1s 過渡方式為ease
        // 'width:' + width * imgs.length + 'px;' + 'height:100%;padding:0;' + 'margin:0;' + 'transition:transform 1s ease';//ease先快後慢;放圖像個數的窗口
        ct.appendChild(this.innerCt);//將innerct放入到dom元素中去

        let circleCt = document.createElement('div');//此處為頁面底部的圓圈
        circleCt.style.cssText = `position:fixed;opacity:0.6;bottom:0px;width:100%;padding:10px 0`;//讓圓圈布局在底部
        circleCt.setAttribute('align', 'center');//效果 劇中
        ct.appendChild(circleCt);
        this.circles = [];

        let ct3 = document.createElement('div');//新建一個div,將最後一個圖片放入其中,再將該div放入innerct中
        ct3.style.cssText = `width:${width}px;height:${height};float:left`;
        ct3.setAttribute('align', 'center');//左右居中
        let img3 = new Image();
        img3.src = imgs[this.pageCount - 1];
        img3.style.cssText = `max-width:${width}px;max-height:${height}px`;
        img3.onload = () => {
            img3.style.marginTop = (height - img3.height) / 2 + 'px';//垂直居中
        }
        ct3.appendChild(img3);
        this.innerCt.appendChild(ct3);

        imgs.forEach((item, index) => {//將圖片按照 list的順序放入其中,並在其中添加圓圈的點擊事件
            let ct1 = document.createElement('div');
            ct1.style.cssText = `width:${width}px;height:${height};float:left`;
            // 'width:' + width + 'px;' + 'height:' + height + 'px;' + 'float:left;';
            ct1.setAttribute('align', 'center');//左右居中
            let img = new Image();
            img.src = item;
            img.style.cssText = `max-width:${width}px;max-height:${height}px`;
            // 'max-width:' + width + 'px;' + 'max-height:' + height + 'px;';
            img.onload = () => {
                img.style.marginTop = (height - img.height) / 2 + 'px';//垂直居中
            }
            ct1.appendChild(img);
            this.innerCt.appendChild(ct1);
            let c = document.createElement('div');
            c.style.cssText = `width:20px;height:20px;
            border-radius:10px;background-coclor:white;
            display:inline-block;margin-right:10px;`;
            this.circles.push(c);
            circleCt.appendChild(c);
            c.addEventListener('click', () => {
                this.sliderTo(index);//點擊小圓點有滑動的效果
            });
        });
        let ct2 = document.createElement('div');//新建一個div,將第一個圖片放入其中,再將該div放入innerct中
        ct2.style.cssText = `width:${width}px;height:${height};float:left`;
        ct2.setAttribute('align', 'center');//左右居中
        let img2 = new Image();
        img2.src = imgs[0];
        img2.style.cssText = `max-width:${width}px;max-height:${height}px`;
        img2.onload = () => {
            img2.style.marginTop = (height - img2.height) / 2 + 'px';//垂直居中
        }
        ct2.appendChild(img2);
        this.innerCt.appendChild(ct2);

        let css = `position:absolute;//es6的新特性,反引號,可以查一下,使用極其方便,好像是加載速度不如''。
        top:50%;
        margin-top: -20px;
        height:40px;opacity:0.6;
        margin:0px auto;
        width:40px;
        padding:0 20px
        line-height:40px;
        background-color:#bbb;
        font-size:28px;
        cursor:pointer;`;
        let btnleft = document.createElement('div')
        btnleft.innerHTML = '<';
        btnleft.style.cssText = css;
        btnleft.style.left = '0px';

        let btnright = document.createElement('div')
        btnright.innerHTML = '>';
        btnright.style.cssText = css + `text-align: right;`;
        btnright.style.right = '0px';

        ct.appendChild(btnleft);
        ct.appendChild(btnright);//設置左右兩個切換按鈕,其下面所添加的點擊事件就是之前思路中所强調的部分。

        btnleft.addEventListener('click', () => {
            if (this.currentPage === 0) {//當在第一個圖片時點擊了左移按鈕。
                this.circles[this.currentPage].style.backgroundColor = 'white';當前的底部圓圈顏色變白。
                this.circles[this.pageCount - 1].style.backgroundColor = 'red';最後一個圖片的底部圓圈的變為選中的顏色 紅色
                let left = 0 * this.width;此時innerct平移的距離為 0 根據此前innerct裏面插入div 的順序,那麼此時呈現的就是最後一個圖片。
                this.innerCt.style.transform = 'translate(' + left + 'px,0px)';
                sleep(1000).then(() => {睡眠1秒完成,此處必須使用es6中的箭頭函數,不如會引起this指向的改變
                    this.innerCt.style.transitionDuration = "0s";調用js中的 transition的api 將過渡時間設置為0
                    this.sliderTo(this.pageCount - 1);常規的移動圖片至最後一張
                });
                sleep(1100).then(() => {同樣等待上面的操作完成後,再將過渡時間設置為1s,此處只需要比上面完成的時間少一點即可
                    this.innerCt.style.transitionDuration = "1s";
                })
                return;
            }
            this.sliderTo(this.currentPage - 1);//當不涉及特色情况時,進行左移即可。
        });
        btnright.addEventListener('click', () => {//同理
            console.log('pagecount', this.currentPage);
            if (this.currentPage === this.pageCount - 1) {
                this.circles[this.currentPage].style.backgroundColor = 'white';
                this.circles[0].style.backgroundColor = 'red';
                let left = -(this.pageCount + 1) * this.width;
                this.innerCt.style.transform = 'translate(' + left + 'px,0px)';
                this.currentPage = 0;
                sleep(1000).then(() => {
                    this.innerCt.style.transitionDuration = "0s";
                    this.sliderTo(0);
                });
                sleep(1100).then(() => {
                    this.innerCt.style.transitionDuration = "1s";
                })
                return;
            }
            this.sliderTo(this.currentPage + 1);


        })
        for (let i = 0; i < this.circles.length; ++i) {
            this.circles[i].style.backgroundColor = 'white';
        }//底部的圓圈初始化

        this.circles[0].style.backgroundColor = 'white';
        this.circles[0].style.backgroundColor = 'red';
        let left = -1 * this.width;
        this.innerCt.style.transform = 'translate(' + left + 'px,0px)';
        this.currentPage = 0;//設置顯示list中的第一個圖片

    }
    sliderTo(num) {
        this.circles[this.currentPage].style.backgroundColor = 'white';
        this.circles[num].style.backgroundColor = 'red';//底部圓圈的切換
        let left = -(num + 1) * this.width;//innerct 平移距離的改變
        this.innerCt.style.transform = 'translate(' + left + 'px,0px)';
        this.currentPage = num;//當前照片的改變
        console.log('pagecurrent::::', this.currentPage);
    }
}

function sleep(time) {//es6增加的异步操作,此處需要异步來完成睡眠
    return new Promise((resolve) => setTimeout(resolve, time));
}

上面代碼講的十分詳細了,我就不過多贅述了。

原文連接見上面

版權聲明
本文為[美劇之神]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/134/202205141235381601.html

隨機推薦