原生js實現響應式全屏輪播圖

聲明:以下方法是剛入門前端實驗產品,高手繞道。


最近做自己網站的時候遇到輪播圖問題。網絡上無數個教程都描述瞭如何做出一個輪播圖,或者如何用jq做出一個自適應輪播圖。對於還沒有時間去了解jq的dba來說,實在沒有精力去了解jq(主要是js還不熟),但是自己琢磨了下好像可以用純js+css3實現自適應輪播。

鑑於是我無聊給我自己做的網站,所以在寫前端的時候沒有考慮太多支持各種老版本瀏覽器,所以兼容性問題不在討論範圍內。


正文:

輪播圖設計思路:

需求要點:
1、自動播放
2、左右按鈕控制變換
3、分頁下標
4、如果做全屏輪播圖,需要考慮屏幕寬度問題

實現思路:
    1、需要一個一級容器存放所有數據,做鼠標移動暫停自動播放需要調用
    2、需要多個二級容器存放內容,思路有兩種:
        第一種各圖片層疊,用position 父模塊relative + 子模塊absolute屬性,
        第二種僅在父級使用position relative屬性或者flex等模式,使其圖片水平橫向擴展
        
        層疊需要從層級z-index屬性或者透明疊層等方向下手,能發展淡入淡出效果
        橫向需要從圖片偏移像素下手,採用left屬性較多,比較容易實現橫向移動過度效果。

        全屏輪播方式建議水平擴展而不是層疊,水平擴展如果是全屏輪播圖需要處理不同屏幕大小之間寬度問題,相對容易實現
        局部輪播按需求可採用層疊等方式

    3、分頁下標和二級容器放在同層級並且浮動到輪播圖父容器上
    4、需要兩個按鈕放到最上層


    offsetwidth  獲取left屬性所需要的自適應屏幕寬度

模塊樣式設計:
    本次使用flex橫向擴展模式
    1、確定一級box寬高
    2、確定二級容器數據,做移動輪播寬度設定需要很長很長的寬度;
    3、圖片容器寬度和需要展示寬度一致
    4、浮動,用flex,移動採用 left
    5、確定按鈕位置
    6、確定下標位置和樣式顏色
    7、自動輪播和鼠標暫停

注意細節:
    1、自適應全屏的選擇,使用flex還是div等
    2、js邊緣處理
    3、分頁下表的移動和點擊操作
    4、自動播放,原理是定時模擬點擊

 

如下圖我做的實驗截圖:

 通過僞類可以讓按鈕在鼠標不在的情況下隱藏。


 19年9.29,重構了代碼,解決了改變窗口大小造成的圖片位移,最後一張到第一張之間的過渡橫拉問題,加入響應式css,自適應各種屏幕,還有唯一一個問題待優化:在改變窗口大小口第一次滑動產生的快速位移,解決思路是寬度監聽端口中增加像素值判斷來優化,後續再嘗試;


 

css部分代碼如下:

/* 輪播圖 */
.img{
    width: 100%;
    height: 100%;
}

.lb_box{
    width: 100%;
    height: 25vw;
}
.lb_imgbox{
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
}
.lb_imgleft{
    width: 100%;
    height: 100%;
    position: relative;
    left: 0;
    transition:left 0.3s linear;
}
.lb_img{
    width: 600%;
    height: 100%;
    display: flex;
}
.lb_li{
    list-style: none;
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
}
.lb_point{
    position: absolute;
    bottom: 0;
    width: 100%;
    z-index: 1;
}
.li_ol{
    display: flex;
    justify-content:center;
    
}
.lb_olli{
    list-style: none;
    border: 0.2vw solid snow;
    border-radius: 50%;
    margin-left: 1%;
    margin-right: 1%;
    padding: 0.5%; 
}
.lb_olli_color{
    background-color: red;
}
@media screen and (max-width:599px){
    .lb_btn{
        display: none;
    }
    .lb_box{
        height: 40vw;
    }
}
.lb_btn{
    position: absolute;
    top: 30%;
    height: 40%;
    background: transparent;
    background-color: rgba(0 , 0, 0, .5);
    border: none;
    width: 3vw;
    z-index: 1;
}
.lb_btnl{
    left: 0;
}
.lb_btnr{
    right: 0;
}
            
/* !輪播圖 */

html代碼如下:

 

 <!-- 輪播圖 -->
        <section-lunbo  style="width: 100%">
            <div id="lb_id" class="lb_box">
                <div class="lb_imgbox">
                    <div class="lb_imgleft">
                        <div class="lb_img">
                            <li class="lb_li"><a href=""><img class="img" src="picture/lunbo/4.jpg" alt=""></a></li>
                            <li class="lb_li"><a href=""><img class="img" src="picture/lunbo/1.jpg" alt=""></a></li>
                            <li class="lb_li"><a href=""><img class="img" src="picture/lunbo/2.jpg" alt=""></a></li>
                            <li class="lb_li"><a href=""><img class="img" src="picture/lunbo/3.jpg" alt=""></a></li>
                            <li class="lb_li"><a href=""><img class="img" src="picture/lunbo/4.jpg" alt=""></a></li>
                            <li class="lb_li"><a href=""><img class="img" src="picture/lunbo/1.jpg" alt=""></a></li>
                        </div>
                    </div>
                    <div class="lb_point">
                        <ol id = 'test' class="li_ol">
                            <li class="lb_olli"></li>
                            <li class="lb_olli"></li>
                            <li class="lb_olli"></li>
                            <li class="lb_olli"></li>
                        </ol>
                    </div>

                    <button id="lb_lbtn" class="lb_btn lb_btnl">left</button>
                    <button id="lb_rbtn" class="lb_btn lb_btnr">right</button>
                </div>
            </div>
        </section-lunbo>

js代碼如下:


// 輪播圖js
window.onload = function(){
    
    var lb_box = this.document.getElementsByClassName("lb_imgleft")[0];

    //初始化默認寬度
    var lb_boxwidth = this.document.body.clientWidth;

    var lb_imglist = this.document.getElementsByClassName("lb_li").length;

    var lbtn = this.document.getElementsByClassName("lb_btnl")[0];

    var rbtn = this.document.getElementsByClassName("lb_btnr")[0];

    var lb_pointlist = this.document.getElementsByClassName("lb_olli");

    var num = 0;
    var newwidth = 0;
    //監聽屏幕寬度響應輪播圖寬度li大小縮放產生的偏移量
    window.onresize = function(){
        var leftsize =  document.body.clientWidth;     
        if(leftsize!=lb_boxwidth && num >0){
            lb_box.style.transition ="none";
            lb_box.style.left = -leftsize +"px";
        }
    }
    
    //點擊事件
    rbtn.onclick = function(){

        num ++;
        //獲取自適應屏幕改變後寬度
        newwidth = document.body.clientWidth;
        if(num>lb_imglist-1){
            num = 2;
        }
        left(newwidth);
        //到最後一張的時候,快速切換到第一張,需要加延時等到倒數第二張切換到最後
        //一張的動作結束才執行,否則立即執行會有左滑效果,延時時間等於動畫時間    
        if(num == lb_imglist-1){
            setTimeout(function del(){
                //清除切換樣式,無感知最後一張到第一張
                lb_box.style.transition ="none";
                lb_box.style.left = -newwidth +"px";
                },300);
        }
    }

    lbtn.onclick = function(){
        num--;
        newwidth = document.body.clientWidth;;
        if(num<0){
            num = lb_imglist-1;
        }
        left(newwidth);  
        if(num == 1){
            setTimeout(function del(){
                lb_box.style.transition ="none";
                lb_box.style.left = -newwidth*(lb_imglist-1) +"px";
                num = lb_imglist-1;
                },300);
        }
    }

    //下標被點擊:獲取點擊位置,切換到點擊頁面
    for(var i=0;i<lb_pointlist.length;i++){
        //設定下標索引
        lb_pointlist[i].setAttribute("p_index",i);
        lb_pointlist[i].onclick =function(){
            num = this.getAttribute("p_index");
            newwidth = document.body.clientWidth;;
            left(newwidth);
        }
    }


    //自動輪播,模擬點擊
    var timer = setInterval(function(){
        rbtn.onclick();
    }, 4000);
    //鼠標移入暫停,移入鼠標清除自動定時器
    var lb_box_f = document.getElementsByClassName("lb_box")[0];
    lb_box_f.onmouseenter = function(){
        clearInterval(timer);
    }
    //移除鼠標繼續定時器
    lb_box_f.onmouseleave = function(){
        timer = setInterval(function(){
            rbtn.onclick();
        }, 4000);
    }

    function left(newwidth){
        lb_box.style.transition ="left 0.3s linear";
        //如果屏幕寬度改變,偏移量按照改變後的寬度設定
        if(0<newwidth && newwidth!=lb_boxwidth){
            lb_box.style.left = -newwidth*num +"px"; 
        }
        else
        {
            lb_box.style.left = -lb_boxwidth*num +"px";
        }
        
        //小圓點
        for(var i=0;i<lb_pointlist.length;i++){
            lb_pointlist[i].style.backgroundColor = "transparent";
            if(num<4){
                lb_pointlist[num].style.backgroundColor = "snow";
            }
            else{

                lb_pointlist[num-4].style.backgroundColor = "snow";
            }
        }
    }

}

 


心得:

1、flex盒子做浮動時,需要定義position屬性,flex默認時static的塊屬性,對於static而言left屬性是沒有效果的,所以需要定義成position以便能使用left操作進行左右移動變換

2、自適應全屏,left所需移動的寬度需要獲取當前屏幕的寬度具體像素,因爲flex定義的百分比寬度不能直接用於left,所以需要用clientwidth獲取當前屏幕的寬度數值

3、由於用的flex盒子,ul寬度是根據百分比定義的,不需要預估屏幕像素大小,同時也不需要去寫一個js監聽屏幕大小來自適應,flex自己能做到自適應,在不同屏幕上自動按比例改變圖像,相對來說少了監聽要簡單些。

4、定時器原理是定時模仿點擊函數即可,當初糾結了好久怎麼實現

5、解決最後一張到第一張之間的過度,出了首尾添加多一張圖片以外,需要讓倒數第二張切換到最後一張的動作做完,所以重置最後一張等於第一張圖片位置時需要加延時函數,否則立即執行會產生倒數第二張立即切換到第一張的左滑效果。延時時間等於動畫時間即可消除左滑效果。

6、高度跟隨寬度,寬度和高度比可以通過padding-botton或者vw來確定,看個人喜好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章