移動端輪播圖(原生JS寫法)


移動端輪播圖功能和PC端基本一致。

實現功能:

  • 可以自動播放圖片
  • 手指可以拖動播放輪播圖

下面詳細地說明具體的實現步驟:

1. 自動播放功能:

① 開啟定時器

② 移動端移動可以使用CSS3的translate移動。注意, 使用translate不需要添加就可以移動

③ 想要圖片優雅的移動,就需要添加過渡效果

2. 自動播放功能-無縫滾動:

① 注意,我們判斷條件是要等到圖片滾動完畢再去判斷,就是過渡完成后判斷

② 此時需要添加檢測過渡完成事件transitionend

③ 判斷條件:如果索引號等於3說明走到最后一張圖片,此時索引號要復原為0

④ 此時圖片需要去掉過渡效果,然后移動

PC端實現無縫滾動的原理是:克隆第一張圖片,然后添加到ul的最后面(appendChild)

  • 把ul第一個li復制一份,放到ul的最后面
  • 當圖片滾動到克隆的最后一張圖片時,讓ul快速的、不做動畫的跳到最左側:left為0
  • 同時num賦值為0,可以從新開始滾動圖片了

在移動端照樣是使用這個方法,但是需要補充的是,由於在移動端可以使用手指拖動的效果,為了避免第一張再往前拖動的時候會出現空白的情況,我們還需要將最后一張圖片克隆放到第一張的前面去,也就是下面這樣:

注意,index是從第一張圖片算起的,並且克隆的第三張圖片是不能算作index里面去的。

3. 小圓點跟隨變化的效果:

① 把ol里面li帶有current類名的選出來去掉類名(remove)

② 讓當前索引號的小li加上current(add)(排他思想)

③ 但是,是等着過渡結束之后變化,所以這個功能要寫到transitionend事件里面

4. 手指滑動輪播圖

① 本質就是ul跟隨手指移動,簡單說就是移動端的拖動元素功能

② 觸摸元素:touchstart:獲取手指初始坐標

③ 移動手指touchmove:計算手指的滑動距離,並且移動盒子

④ 離開手指touchend:根據滑動的距離分不同的情況

⑤ 如果移動距離小於某個像素,就回彈到原來的位置

⑥ 如果移動距離大於某個像素就滑動到上一張或者下一張

性能優化1:當我們點擊輪播圖的圖片時,又不想移動了,這時候手指離開需要執行一大段代碼。優化辦法為:加一個flag全局變量,只有當手指真的移動了,才執行手指離開的一系列代碼操作

性能優化2:如果屏幕比較長,手指在移動輪播圖的過程可能會滾動屏幕。優化方法為:取消默認滾動屏幕的行為。在touchmove事件里加上e.preventDefault();即可。

    <!-- 頁面布局 -->
    <div class="focus">
        <ul>
            <li><img src="upload/focus3.jpg" alt=""></li>
            <li><img src="upload/focus1.jpg" alt=""></li>
            <li><img src="upload/focus2.jpg" alt=""></li>
            <li><img src="upload/focus3.jpg" alt=""></li>
            <li><img src="upload/focus1.jpg" alt=""></li>
        </ul>
        <!-- 輪播圖中的小圓圈 -->
        <ol>
            <li class="current"></li>
            <li></li>
            <li></li>
        </ol>
    </div>
    <!-- 焦點圖模塊 end -->
/* 焦點圖模塊樣式 */
.focus {
    overflow: hidden;
    position: relative;
    padding-top: 44px;
}
.focus img {
    width: 100%;
}
.focus ul {
    /* ul沒有高度,里面的子元素又是浮動的,必然會引起格式混亂
    因此需要清除浮動 */
    overflow: hidden;
    width: 500%;
    /* 顯示第一張圖片,而不是復制的第三張圖片 */
    margin-left: -100%;
}
.focus ul li {
    float: left;
    /* 注意:圖片的寬度為100%,占滿父盒子,而圖片的父盒子小li沒有寬度,則找ul
       而ul得寬度設為500%,所以圖片得寬度也被拉長了
       因此需要給li設置寬度,每個小li占ul的1/5 */
    width: 20%;
}
.focus ol {
    position: absolute;
    bottom: 5px;
    right: 5px;
    margin: 0;
}
.focus ol li {
    /* 使其變成行內塊元素,就可以浮動一排顯示 */
    display: inline-block;
    width: 5px;
    height: 5px;
    border-radius: 2px;
    background-color: #fff;
    list-style: none;
    transition: all .3s;
}
.focus ol li.current {
    width: 15px;
}
// JS邏輯代碼
window.addEventListener('load', function() {
    // 1. 獲取元素
    var focus = document.querySelector('.focus');
    var ul = focus.children[0];
    var ol = focus.children[1];
    // 獲得focus的寬度
    var w = focus.offsetWidth;
    // 2. 利用定時器自動輪播圖片
    var index = 0;
    var timer = setInterval(function() {
        index++;
        var translateX = -index * w;
        // 添加動畫效果
        ul.style.transition = 'all .3s';
        ul.style.transform = 'translateX(' + translateX + 'px)';
    }, 2000);
    // 等着過渡完成之后,再去判斷,監聽過渡完成的事件transitionend
    ul.addEventListener('transitionend', function() {
        // 無縫滾動
        if (index >= 3) {
            index = 0;
            // 去掉過渡效果,這樣讓ul快速的跳到目標位置
            ul.style.transition = 'none';
            // 利用最新的索引號乘以寬度,繼續滾動圖片
            var translateX = -index * w;
            ul.style.transform = 'translateX(' + translateX + 'px)';
        } else if (index < 0) {
            index = 2;
            // 去掉過渡效果,這樣讓ul快速的跳到目標位置
            ul.style.transition = 'none';
            // 利用最新的索引號乘以寬度,繼續滾動圖片
            var translateX = -index * w;
            ul.style.transform = 'translateX(' + translateX + 'px)';
        }
        // 3. 小圓點跟隨變化
        // 把ol里面li帶有current類名的選出來,去掉類名remove
        ol.querySelector('.current').classList.remove('current');
        // 讓當前索引號的li加上current類名add
        ol.children[index].classList.add('current');
    });
    // 4. 手指滑動輪播圖
    // 觸摸元素touchstart:獲取手指初始坐標
    var startX = 0;
    var moveX = 0;  // 后面會使用這個移動距離,所以要定義為全局變量
    var flag = false;  //用來標志手指是否真的移動,還是只是點擊
    ul.addEventListener('touchstart', function(e) {
        startX = e.targetTouches[0].pageX;
        // 手指觸摸的時候就停止定時器
        clearInterval(timer);
    });
    // 移動手指touchmove:計算手指的滑動距離,並且移動盒子
    ul.addEventListener('touchmove', function(e) {
        // 計算移動距離
        // e.targetTouches[0]為第一個手指,[1]表示第二個手指
        moveX = e.targetTouches[0].pageX - startX;
        // 移動盒子:盒子原來的位置 + 手指移動的距離
        var translateX = -index * w + moveX;
        // 手指拖動的時候,不需要動畫效果,所以要取消過渡效果
        ul.style.transition = 'none';
        ul.style.transform = 'translateX(' + translateX + 'px)';
        flag = true;
        e.preventDefault();   //組織滾動屏幕的行為
    });
    // 手指離開,根據移動距離去判斷是回彈還是播放上一張或者下一張
    ul.addEventListener('touchend', function(e) {
        // 只有手指移動過了,才執行下面的代碼
        if (flag) {
            //(1)如果移動距離大於50像素,則播放上一張或者下一張
            if (Math.abs(moveX) > 50) {
                // 如果是右滑就是播放上一張,moveX是正值
                if (moveX > 0) {
                    index--;
                } else {
                    // 如果是左滑就是播放下一張,moveX是負值
                    index++;
                }
                // 用最新的index乘以寬度
                var translateX = -index * w;
                ul.style.transition = 'all .3s';
                ul.style.transform = 'translateX(' + translateX + 'px)';
            } else {
                //(2)如果移動距離小於50像素就回彈
                var translateX = -index * w;
                ul.style.transition = 'all .1s';
                ul.style.transform = 'translateX(' + translateX + 'px)';
            }
        }        
        // 手指離開的時候就重新開啟定時器
        // 注意:開啟定時器之前要先清空之前的定時器,保證當前只有一個定時器在執行
        clearInterval(timer);
        timer = setInterval(function() {
            index++;
            var translateX = -index * w;
            // 添加動畫效果
            ul.style.transition = 'all .3s';
            ul.style.transform = 'translateX(' + translateX + 'px)';
        }, 2000);
    });
});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM