1. 程式人生 > >JS實現某東移動web輪播圖

JS實現某東移動web輪播圖

移動web輪播圖

參考例項,可以從中儲存輪播圖的圖片,這裡我們放入uploads的資料夾下,將八張圖片一次改為l1.jpg,l2.jpg…

https://m.jd.com/

HTML

  1. 這裡要放入十張圖片,因為手指滑動的時候要從第一張滑動到最後一張,是無縫滑動,當然可以用原生的JS進行新增
  2. 最終我們可以通過移動ul來達到輪播的效果,所以ul的寬度要剛好放得下十張圖片
  3. ol下的li是分頁器,也就是我們看到的圓圈,類.current為選中狀態
  4. clearfix類是清除浮動
<div class="jd_banner">
<ul class="jd_wrap clearfix"> <li><a href="javascript:;"><img src="uploads/l8.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l1.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l2.jpg"
alt="">
</a></li> <li><a href="javascript:;"><img src="uploads/l3.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l4.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l5.jpg"
alt="">
</a></li> <li><a href="javascript:;"><img src="uploads/l6.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l7.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l8.jpg" alt=""></a></li> <li><a href="javascript:;"><img src="uploads/l1.jpg" alt=""></a></li> </ul> <ol> <li class="current"></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ol> </div>

css樣式

.clearfix::before,
.clearfix::after{
    content: "";
    display: block;
    height: 0;
    line-height: 0px;
    clear: both;
    visibility: hidden;
}

.jd_banner {
  max-width: 640px;
  min-width: 320px;
  margin: 100px auto;
  width: 100%;
  position: relative;
  overflow: hidden;
}
.jd_banner .jd_wrap {
  width: 1000%;
  transform: translateX(-10%);
}
.jd_banner .jd_wrap li {
  width: 10%;
  float: left;
}
.jd_banner .jd_wrap li img {
  width: 100%;
}
.jd_banner ol {
  height: 10px;
  position: absolute;
  left: 50%;
  bottom: 3px;
  transform: translateX(-50%);
}
.jd_banner ol li {
  width: 6px;
  height: 6px;
  float: left;
  border: 1px solid #fff;
  margin-left: 10px;
  border-radius: 50%;
}
.jd_banner ol li.current {
  background: #fff;
}

輪播圖效果

JS

  1. 我們主要通過控制index,translateX,監聽過渡動畫的結束(webkitTransitionEnd)來實現輪播
  2. 對index進行限制
  3. 相同的程式碼進行封裝
  4. 優化程式碼
var jdCon = document.querySelector('.jd_banner')
	var ul = document.querySelector('.jd_banner>.jd_wrap')
	var index = 1
	var li = ul.querySelectorAll('li')
	var olLi = document.querySelectorAll('ol>li')
	var imgWidth = li[0].offsetWidth
	// 過渡移動的效果
	var transit = function(move){
		var move = move || 0
		ul.style.transition = 'all 0.5s linear'
		ul.style.transform = `translateX(${-imgWidth*index+move}px)`
	}
	// 瞬間定位效果
	var moment = function(distanceMove){
		var distanceMove = distanceMove || 0
		ul.style.transform = `translateX(${-imgWidth*index+distanceMove}px)`
		ul.style.transition = 'none'
	}
	window.onresize = function(){
		imgWidth = li[0].offsetWidth
	}
	var timer1 = setInterval(function(){
		index++;
		transit()
	}, 1000)
	ul.addEventListener('webkitTransitionEnd', function(){
		if(index>li.length-2){
			index = 1
			moment()
		}
		if(index<1){
			index = li.length-2
			moment()
		}
		document.querySelector('.current').classList.remove('current')
		olLi[index-1].classList.add('current')
	})
	var distanceStart = 0;
	var move = 0;
	var distanceEnd = 0;
	jdCon.addEventListener('touchstart',function(e){
		clearInterval(timer1)
		distanceStart = e.touches[0].clientX
	})
	jdCon.addEventListener('touchmove',function(e){
		var distance = e.touches[0].clientX
		move = distance - distanceStart
		moment(move)
	})
	jdCon.addEventListener('touchend',function(){
		if(move>imgWidth/2){
			index--
			transit()
		}else if(move<-imgWidth/2){
			index++
			transit()
		}else{
			transit()
		}
		distanceStart = 0;
		move = 0;
		distanceEnd = 0;
		timer1 = setInterval(function(){
			index++;
			transit()
		}, 1000)
	})

整體思路

  1. 首先做好佈局,ul的子元素li要在一行上,無縫連結
  2. 利用css,ul的寬度為1000%, 設定transform: translateX(-10%);,使得不會顯示展示給使用者的最後一張圖片,顯示第一張圖片
  3. 自動播放輪播圖
  4. 利用定時器,讓index每次加1,然後過渡滾動一張圖片
var timer1 = setInterval(function(){
		index++;
		ul.style.transition = 'all 0.5s linear'
		ul.style.transform = `translateX(${-imgWidth*index}px)`
	}, 1000)
  1. 監聽webkitTransitionEnd,過渡動畫結束時,清除當前的類.current,給ol下的li[index]新增一個類
  2. 過渡動畫結束後,如果index過大,我們要對其進行限制,當index為9,此時介面顯示的是第十張圖片,也就是使用者看到的第一張圖片,所以我們瞬間(在0s)讓其移動到第一張,在令index=1
ul.addEventListener('webkitTransitionEnd', function(){
		// 當時間過渡結束
		// 新增.current
		if(index>8){
			// 當第一張移動完成後
			// 瞬間讓index變為1
			ul.style.transform = `translateX(${-imgWidth}px)`
			ul.style.transition = 'none'
			index = 1
		}		document.querySelector('.current').classList.remove('current')
		olLi[index-1].classList.add('current')
	})
  1. ul跟隨著手指的滑動而滑動,當手指滑動多少,ul跟著滑動多少
var distanceStart = 0;
	var move = 0;
	var distanceEnd = 0;
jdCon.addEventListener('touchstart',function(e){
		clearInterval(timer1)
		distanceStart = e.touches[0].clientX
	})
	jdCon.addEventListener('touchmove',function(e){
		var distance = e.touches[0].clientX
		move = distance - distanceStart
		ul.style.transform = `translateX(${-imgWidth*index+move}px)`
		ul.style.transition = 'none'
	})
  1. 滑動結束時做吸附效果
  2. 向右滑動時,如果滑動大於圖片二分之一的寬度,當手指放開則加上過渡動畫效果移動到上一張圖片,此時我們移動始終是控制index
if(move>imgWidth/2){
			index--
			ul.style.transition = 'all 0.5s linear'
			ul.style.transform = `translateX(${-imgWidth*index}px)`
		}
  1. 向左滑動時,如果滑動大於圖片二分之一的寬度,當手指放開則加上過渡動畫效果移動到下一張圖片,此時我們移動始終是控制index
else if(move<-imgWidth/2){
			index++
			ul.style.transition = 'all 0.5s linear'
			ul.style.transform = `translateX(${-imgWidth*index}px)`
		}
  1. 其它情況保持顯示現狀的圖片
else{
			ul.style.transition = 'all 0.5s linear'
			ul.style.transform = `translateX(${-imgWidth*index}px)`
		}
  1. 最後所有的清0,開啟定時器
  2. 相同程式碼封裝,測試是否有bug,發現右滑有問題--------始終通過控制index來實現移動和切換ol分頁器,要對index進行限制。對數字通過ul下的li.length來控制,將程式碼封裝成可呼叫,可讀性,邏輯性的程式碼
if(index<1){
			ul.style.transform = `translateX(${-imgWidth*8}px)`
			ul.style.transition = 'none'
			index = 8
		}

步驟

/*
	獲取 必須知道的 變數

	步驟1: 不考慮過渡效果 直接 刷刷刷的 切換
		定時器中 index++
			    判斷是否越界
			   修改 輪播圖ul的 位置
			   考慮到 索引從1開始
			   css 預設 讓ul 往左邊竄一個螢幕寬度

	步驟2:	  下方的 索引li標籤 修改 外觀
		由於我們是使用.current 標示當前的索引值
		清空所有li的 class
		為當前的那個 li 新增current

	步驟3:然切換有動畫效果
		使用css3中的transition
		.style.transition ='all .3s';
		在獲取的時候 進行新增即可

	步驟4:當我切換到 最後一張時 瞬間 切到 第一張
		關閉過度
		瞬間切換到第一張

	步驟5:對程式碼 進行重構 新增進來了 過渡結束知識點
		由於 我們在修改 ul的位置時 會使用過度
		當註冊了 過渡結束事件之後,每次 過渡完畢 都會 呼叫該事件
			將 判斷 index  是否 越界 以及 修改 索引的 程式碼 全部 遷移到 過渡結束事件中

			定時器邏輯
				index++;

				修改 ul的 位置 ->開始過渡

			過渡結束事件邏輯
				判斷 index是否有效
					進行修正
				修改索引li標籤的 顯示

	步驟6: 使用touch事件,實現 手指 撥動 ul滑動 效果
		touchstart
			記錄開始值
			關閉定時器
			關閉過渡效果
		touchmove
			計算移動值
			修改ul的位置(在原始值的基礎上進行修改,沒有過渡效果的)
		touchend
			記錄移動的距離(?)
			開啟定時器(*)

*/

疑問

  1. 寬高必須考慮到移動web的適配方案
  2. 可能大家會把ul進行定位,ul定位(absolute),我們就無法把父盒子撐開,也就是父盒子jd_banner就沒有高度,到時ol也很難定位,影響頁面佈局等問題
  3. 直接給父盒子設定高度,但是我們這個高度不好設定,因為不同的螢幕圖片高度是不一致的
  4. 使用translateX來移動邏輯會更簡單些
  5. 注意要樣式重置,比如img要去掉基線
  6. clearfix可以不加,因為父盒子jd_banner已經設定overflow: hidden;會觸發bfc