輪播,英文slider,也就是幻燈片的意思,咱們能夠手動或者自動切換一張張的照片達到顯示的目的。各大電商網站都會使用輪播來展現商品,能夠在相對較小的空間裏,實現多種展現。css
通常,咱們能夠兩種方法來實現輪播,例如,核心思路使用透明度來切換照片,使用距離來平移照片。在這裏咱們使用平移的方式來實現輪播,並經過幾組核心數據來實現slide的切換,此外,通常還具備多種方法能夠實現無縫切換。html
咱們實現的輪播,所須要具備的功能能夠分爲如下幾部分:app
咱們設置兩個容器,經過在父容器使用transform
進行左右平移,translateX()
是相對於自身的寬度,而在子容器裏經過絕對定位來進行平移,其中left
屬性相對的是父容器的寬度,這樣父容器平移100%,子容器距離左邊-100%,就能夠相互抵消。ide
HTML結構以下組件化
<div id="m-slider"> <div class="slide"> <img > </div> <div class="slide"> <img > </div> <div class="slide"> <img > </div> </div> <button id="prev">prev</button> <button id="next">next</button>
CSS以下,略有刪減,能夠參考源碼網站
#m-slider { position: relative; width: 100%; height: 100%; transform: translateX(-100%); } .slide { position: absolute; } .slide:nth-child(1) { left: 0%; } .slide:nth-child(2) { left: 100%; } .slide:nth-child(3) { left: 200%; }
此時咱們知道能夠顯示第二張圖片。this
數據模型:url
slideIndex
爲slide的索引,取值爲0,1,2,表示始終只有三張圖片在HTML結構當中。offset
表示當前距離最左邊切換圖片的數量,每次向後切換時,都會加1,取值範圍爲1~圖片的總數量相關說明:.net
normalIdx()
方法是一個將數字轉換爲len
範圍的方法,接收索引和長度,返回一個在len
以內的數值,這裏的len
固定爲3go()
方法,接收1或者-1,分別表示向前和向後移動,以向前移動爲例,此時作了兩件事,相關因此會更新,改變容器的偏移,主要是offset
和slideIndex
會發生變化,都須要調用規範化方法,使其數值始終處於3以內。calcDistance()
方法爲計算移動距離的方法,主要有父容器和slide
的距離計算。var slider = document.getElementById('m-slider') var slides = document.querySelectorAll('.slide') var prev = document.getElementById('prev'); var next = document.getElementById('next'); var slideIndex = 1; // one of 0,1,2 var offset = 1; // 顯示的slide距容器最左邊的偏移量 prev.onclick = function() { go(-1); } next.onclick = function() { go(1); } function normalIdx(index,len) { return (index + len) % len; } function go(foreward) { offset += foreward; // 向右移動了一個,全部偏移量也須要加一 slideIndex += foreward; // 向右移動了一個,因此加一,須要歸三化 slideIndex = normalIdx(slideIndex,3); var prevIndex = normalIdx(slideIndex - 1,3); var nextIndex = normalIdx(slideIndex + 1,3); calcDistance(prevIndex,slideIndex,nextIndex,offset); } function calcDistance(prevIndex,slideIndex,nextIndex,offset) { slider.style.transform = `translateX(${-100*offset}%)` //console.log(slider.style.transform) console.log(offset) // slide offseet slides[prevIndex].style.left = `${100*(offset-1)}%`; slides[slideIndex].style.left = `${100*offset}%`; slides[nextIndex].style.left = `${100*(offset+1)}%`; }
每次切換時,slide
的left
屬性都會改變,父容器的transform
也發生改變,相互抵消,輕鬆實現無縫切換,注意: 咱們這裏只設置了三張照片,恰好與要求一致,並無對相關數據進行計算處理。插件
/** 無論輪播的照片有多少,只有三欄是常駐的 * ------------------- * | | | | * ------------------------------- * | | | | | | * | | | | | | * | | 1 | 2 | 3 | | * | | | | | | * | | | | | | * ------------------------------- * | | | | * ------------------- */
咱們將前面寫的業務代碼,用面向對象的思想來重構一下。
HTML發生一些改變,咱們將Img經過JS動態注入
<div id="m-slider"> <div class="slide"> </div> <div class="slide"> </div> <div class="slide"> </div> </div> <button id="prev">prev</button> <button id="next">next</button>
JS部分,這裏`pageNum
表示圖片的總數量,能夠爲任意數字,renderImg()
爲渲染圖片的方法,主要在切換的時候改變圖片的url,第一次須要進行初始化。
// Component class Slider { constructor(el) { // omit some code this.offset = 1;// 偏移量,即個數 this.slideIndex = 1;// slide index one of 0, 1, 2 this.pageIndex = 1;// page index of total pictures this.pageNum = 6;// total pictures } // 標準化index,使index始終爲0,1,2中的一個 normalIdx(index,len) { return (index + len) % len; } // slide move according to the flag go(flag) { // 1. offset and slideIndex change this.offset += flag; this.pageIndex += flag; const slideIndex = this.slideIndex = this.normalIdx( this.slideIndex += flag,3); // 計算移動距離 this.calcDistance(); } // style change calcDistance() { const offset = this.offset; const slideIndex = this.slideIndex; // index const prevIndex = this.normalIdx( slideIndex - 1, 3) const nextIndex = this.normalIdx( slideIndex + 1, 3) this.pageIndex = this.normalIdx(this.pageIndex,this.pageNum) // 2. container and slide move this.container.style.transform = `translateX(${-100 * (offset)}%) `; this.slides[prevIndex].style.left = `${100 * (offset - 1)}%`; this.slides[slideIndex].style.left = `${100 * offset}%`; this.slides[nextIndex].style.left = `${100 * (offset + 1)}%`; //console.log(this.pageIndex,this.slideIndex) this.renderImg(this.pageIndex,this.slideIndex); } renderImg(pageIndex,slideIndex) { for(let i = -1; i <= 1; i++) { const index = (slideIndex+i+3) % 3; // 決定圖片的url和left漂移 let img = this.slides[index].querySelector('img'); let picId = this.normalIdx( pageIndex + i, this.pageNum) + 1; // 頁面初始化使用,運行一次 if(!img) { img = document.createElement('img'); this.slides[index].appendChild(img); } img.src = 'http://placehold.it/300x200&text=' + picId + '-Mint'; } } start() { this.bindEvents() this.renderImg(1,1); } } const mySlider = new Slider('m-slider'); mySlider.start()
添加了nav功能,點擊對應的小按鈕,便可跳轉到指定的slide上
後期將考慮將輪播進行組件化,封裝成獨立的組件,添加更多可定製的功能。