從前只做過PC端輪播組件,實現方式也是margin負值和setTimeout。前一陣看到一個比較精簡的移動端輪播組件的實現https://github.com/ximan/swipeSlide/blob/gh-pages/js/swipeSlide.js,用translate代替margin負值,並且添加了對touch事件的處理。在這里總結一下這個組件的實現。
所有的li絕對定位於容器左上角,寬度100%,高度100%。
1.組件init步驟:
1)如果設定了連續輪播,則復制first slide到最后一幀后,last slide到第一幀前。
2)計算輪播距離(幻燈片寬度或高度。下面都假設是寬度)width.
3)為每一個li設置transition屬性(好像沒用)
4)第0個li向左translate width, 第1個li不移動,第2個li向右translate width, 依次類推。這樣所有的幻燈片從層疊到排列。
5)調用antoSlide()開始輪播
2. autoSlide的實現:
1)停止autoSlide定時器
2)setInterval設置每speed ms執行一次fnSlide('next'),播放下一slide, 每次播放300ms. 定時器指針賦值給autoSlide.
3. fnSlide實現。
組件有一個全局_index. 每次播放根據_index的值。
1)如果播放下一slide(next), _index++
如果播放上一slide, _index--
如果固定某個slide, _index = _slide
也可能以上情況都不是,那就是默認播放完當前_index對應的slide. 這種情況是針對當前slide因為觸摸事件停止播放而后又恢復播放的情況,下文將描述。
2)如果是循環播放:
如果當前已到最后一幅幻燈片且仍需播放下一幻燈片,則正常播放下一幅幻燈片,執行fnScroll(300),然后設置_index = 0;300ms以后執行fnScroll(0)將ul瞬間移動到第一幅幻燈片。 //播放的是位於最后的第一幅幻燈片,300ms的時間是自定義。
如果當前已到第一幅幻燈片且仍需播放上一幅幻燈片,則正常播放上一幅幻燈片,執行fnScroll(300), 然后設置_index = length - 1; 300ms以后執行fnScroll(0)將ul瞬間移動到最后一幅幻燈片。//播放的是位於最前面的最后一幅幻燈片,300ms可自定義。
如果以上兩種情況都不是,則執行fnScroll(300)正常滾動。
3)如果不是循環播放:
如果當前已到最后一幅且向后,設置index = 0, 如果是第一幅且向前,設置index = length - 1; 然后執行fnScroll(300);這樣的效果是在300ms內幻燈片從第一幅快進到最后一幅或者從最后一幅迅速回退到第一幅,其實不是太好看。
3. fnScroll函數的實現
1)根據參數設置ul的transition時間為0或300ms等等
2)ul根據_index的值translate. 對於每一幅幻燈片,ul translate的距離是固定的,與translate開始時ul的位置無關。所以在觸摸回調中,fnScroll可能只是移動了半幅幻燈片。
4. 對觸摸事件的處理
1)touchstart:
isScrolling=undefined.
moveDistance = 0
記錄startX與startY
2)touchmove:
暫停autoSlide;
計算已移動的距離moveDistance;
如果是首次移動,則根據x移動距離與y移動距離的大小判斷是滾動還是滑動。如果是滾動則不作處理,如果是滑動,設置ul transition的時間為0
如果不是循環播放,已經到最后一幅幻燈片還要向后或者已到第一幅幻燈片還要向前,設置moveDistance = 0;
ul translate moveDistanc距離
3)touchend:
如果當前是滾動,則恢復autoSlide.
如果滑動距離小於50px,視作播放當前幻燈片,fnScroll('')
如果滑動距離大於50px,視作播放下一幅或上一幅幻燈片,fnScroll('next')或者fnScroll('prev');
恢復autoSlide.