js原生實現輪播圖(二)

接上一篇,第一個問題:我們要考慮圖片數量,當圖片數量<=1時,不顯示指示器:

    //第二步:添加指示器
    var indicator_li = null;
    if (banner_li.length > 1) {
        var ul_indicator = document.getElementById("ul_indicator");
        var indicatorHtml = "";
        for (let i = 0; i < banner_li.length - 2; i++) {//要按原來的圖片數量
            indicatorHtml += "<li></li>"
        }
        ul_indicator.innerHTML = indicatorHtml;
        indicator_li = ul_indicator.getElementsByTagName("li");
    }

第二個問題:實現移動端手勢滑動操作:監聽觸摸操作,我們需要用到addEventListener方法,並且需要監聽至少三個手勢:
按下:關閉定時器並記錄手指落點座標

ul_banner.addEventListener("touchstart", function () {

})

滑動:根據滑動動態座標與手指落點座標計算動態滑動距離

ul_banner.addEventListener("touchmove", function () {

})

擡起:做一些還原操作如再次開啓定時器

ul_banner.addEventListener("touchend", function () {

})

另外要計算好,手指在屏幕滑動的距離,即

moveX=手指擡起點-手指落點

手指往右滑動,輪播圖往左移動,moveX就爲負數,反之爲正數,因爲我們上面的屬性left用的是百分比(也可以用px具體值),所以我們要根據滑動距離/屏幕寬度計算滑動的百分比,再加上原來的ul偏移的百分比得到最終的left偏移量!

另外一個優化點是,手指滑動圖片擡起後,圖片的位置該如何顯示?我這裏是做了一個判斷處理,如果滑動圖片距離超過50%,則在擡起時自動滑動到上一個或下一個圖片,如果未到50%,則還原。

瞭解滑動原理及計算方法後,其實下面就很好寫了:

function bannerCarousel() {
    // 第一步:獲取banner li img列表,將列表第一張圖片複製添加到最後一位,最後一張圖片複製添加到第一位;
    //以本例4張圖片爲例,將第4張圖片複製一份放到第一位,將第1張圖片放置到最後一位,最後得到6張圖片,
    // 這樣每次輪播到position=0或者5時,將其位置重置爲4或1,以實現無限滾動輪播
    var ul_banner = document.getElementById("ul_banner");
    var banner_li = ul_banner.getElementsByTagName("li");
    var banner_li_first = banner_li[0];
    var banner_li_last = banner_li[banner_li.length - 1];
    ul_banner.appendChild(banner_li_first.cloneNode(true));//將第一張圖片複製一份添加到最後一位
    ul_banner.insertBefore(banner_li_last.cloneNode(true), ul_banner.firstChild);//將最後一張圖片複製一份添加到第一位
    ul_banner.style.width = banner_li.length * 100 + "%";//寬度爲6張圖片寬度
    for (let i = 0; i < banner_li.length; i++) {
        banner_li[i].style.width = 100 / banner_li.length + "%";
    }
    ul_banner.style.left = "-100%";//因首位添加圖片後,需要將整體定位到第2張圖片(實際爲banner第一張)

    //第二步:添加指示器
    var indicator_li = null;
    if (banner_li.length > 1) {
        var ul_indicator = document.getElementById("ul_indicator");
        var indicatorHtml = "";
        for (let i = 0; i < banner_li.length - 2; i++) {//要按原來的圖片數量
            indicatorHtml += "<li></li>"
        }
        ul_indicator.innerHTML = indicatorHtml;
        indicator_li = ul_indicator.getElementsByTagName("li");
    }

    //第三步:開啓定時器
    var page_index = 1;//初始位置爲1
    var timer = function () {
        page_index++;
        ul_banner.style.transition = "left 0.5s";
        ul_banner.style.left = -page_index * 100 + "%";
        changeIndicator();
        reLoadPosition();
    };
    var interval = setInterval(timer, 2000);

    //指示器改變
    var changeIndicator = function () {
        if (indicator_li != null) {
            for (var i = 0; i < indicator_li.length; i++) {
                indicator_li[i].style.backgroundColor = "#ccc";
            }
            if (page_index === 0 || page_index === banner_li.length - 2) {//最後一張
                indicator_li[banner_li.length - 3].style.backgroundColor = "#fff";
            } else if (page_index === banner_li.length - 1) {
                indicator_li[0].style.backgroundColor = "#fff";
            } else {
                indicator_li[page_index - 1].style.backgroundColor = "#fff";
            }
        }
    }

    //重置banner位置
    var reLoadPosition = function () {
        setTimeout(function () {//延時操作,等待0.5s動畫執行完畢後再執行以下操作
            if (page_index === 0) {
                page_index = banner_li.length - 2;
                ul_banner.style.transition = "none";
                ul_banner.style.left = (-page_index * 100) + "%";
            } else if (page_index === banner_li.length - 1) {
                page_index = 1;
                ul_banner.style.transition = "none";
                ul_banner.style.left = (-page_index * 100) + "%";
            }
        }, 500);
    }


    //滑動監聽
    var screenW = window.screen.width;
    var startX, w_current_percent, w_move_percent;
    ul_banner.addEventListener("touchstart", function () {
        clearInterval(interval);
        var touch = event.targetTouches[0];
        startX = touch.clientX;
        w_current_percent = -page_index * 100;//當前left的百分比
    });
    ul_banner.addEventListener("touchmove", function () {
        var touch = event.targetTouches[0];
        var moveX = touch.clientX - startX;
        w_move_percent = moveX / screenW * 100;//跟隨手指移動的百分比
        ul_banner.style.transition = "none";//重要:一定不要忘記清除過渡效果
        ul_banner.style.left = (w_current_percent + w_move_percent) + "%";

    });
    ul_banner.addEventListener("touchend", function () {
        //如果左右滑動<寬度一般,則還原爲原來的位置,否則,滑動到上一位或下一位
        if ((w_move_percent < 50 && w_move_percent > 0) || (w_move_percent < 0 && w_move_percent > -50)) {
            ul_banner.style.left = w_current_percent + "%";
        } else if (w_move_percent > 50) {//往右滑動一位
            page_index--;
            ul_banner.style.transition = "left 0.5s";
            ul_banner.style.left = (w_current_percent + 100) + "%";
            changeIndicator();
            reLoadPosition();
        } else if (w_move_percent < -50) {//往左滑動一位
            page_index++;
            ul_banner.style.transition = "left 0.5s";
            ul_banner.style.left = (w_current_percent - 100) + "%";
            changeIndicator();
            reLoadPosition();
        }
        interval = setInterval(timer, 2000);
    });
}

其中重要的一點,在move過程中,一定不要忘了清除過渡效果:

ul_banner.style.transition = "none";

難點或者複雜點其實就是,滑動距離的計算,手指擡起時圖片位置顯示計算,以及指示器顯示計算,這幾點弄明白後,實現起來就不在話下了!

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