1. 頁面布局
1.1 頁面框架
<body><div class="box"><div class="tupian"><img src="4.webp" alt=""><img src="1.webp" alt=""><img src="2.webp" alt=""><img src="3.webp" alt=""><img src="4.webp" alt=""><img src="1.webp" alt=""></div><ul><li data-aa="0" class="aaa"></li><li data-aa="1"></li><li data-aa="2"></li><li data-aa="3"></li></ul></div>
</body>
1.2css樣式
<style>*{margin: 0;padding: 0;}.box {position: relative;/* 在移動端如果不設置下面樣式 可以拖動 */overflow: hidden;}.tupian img {float: left;width: 16.66%;}.tupian {width: 600%;margin-left:-393px;}ul {position: absolute;top: 300px;right: 20px;}ul li {float: left;margin-left: 30px;background-color: #fff;display: block;width: 20px;height: 10px;}.aaa {background-color: coral;}</style>
2. 實現自動輪播
2.1 獲取用到元素
var box = document.querySelector('.box')var tupian = document.querySelector('.tupian')var ul = document.querySelector('ul')
2.2 通過css3的 transition 和 transform 屬性實現動畫效果
- 創建全局變量num作為輪播圖的計數器
- 創建全局變量imgWidth 此變量就是整個box的寬度
- 創建一個定時器 時隔3秒觸發一次 num++ 同時執行下面代碼:
var translate = -num * imgWidth 整體tupian向左每次移動一張圖片寬度- 通過transition實現過渡效果
var timer = setInterval(function () {num++var translate = -num * imgWidth//設置元素的移動在2s內完成 給元素添加過度tupian.style.transition = 'all 1s'tupian.style.transform = 'TranslateX(' + translate + 'px)'}, 3000)
以上代碼計時器開啟后會不斷切換寬度 當num>4后沒有圖片顯示 當num<0后前方也沒有圖片
2.3 解決上面問題 實現重復輪播圖片
- 通過給 tupian 添加 transitionend 事件 (當transition過渡效果完成后觸發此事件)
- 在此事件中通過判斷num==4時 將tupian.style.transform的值設為0 也就是回到第一張位置
- 同時將取消過度效果
- 此事件中添加判斷
當num==4時也就是最后一張圖片
當num<0時也就是第一張圖片(后補那張和最后一張相同)
//過度執行結束后 會觸發 transitionend 事件tupian.addEventListener('transitionend', function () {// console.log(num)if (num == 4) {num = 0//取消過度tupian.style.transition = 'none'tupian.style.transform = 'TranslateX(0px)'}else if(num<0){num=3var translatex=-num*imgWidthtupian.style.transition = 'none'tupian.style.transform = 'TranslateX('+translatex+'px)'}
3. 手指拖動實現輪播
1. 手指觸摸到元素上 停止輪播圖自動播放
2. 判斷手指的移動方向 然后圖片向這個方向移動
3. 判斷手指的移動距離 如果超出范圍就切換輪播圖 如果沒有超出這個范圍 則繼續顯示原來的輪播圖
3.1 設置全局變量
//獲取手指的初始坐標
var startx = 0
//獲取圖片的初始坐標
var tupianx = 0
//手指的移動距離
var movex = 0
3.2 為 tupian 添加手指按下事件
事件中:
- 停止輪播圖
- 獲取手指按下時的坐標 賦值給變量 startx
- 獲取按下手指時的tupian坐標
tupian.addEventListener('touchstart', function (e) {//手指按下時將現在坐標賦值給 startxstartx = e.targetTouches[0].pageXtupianx = tupian.offsetLeft//清除定時器clearInterval(timer)timer = null})
3.3 為 tupian 添加手指在DOM上的移動事件
事件中:
- 通過e.targetTouchrs[0].pageX不斷獲取手指的坐標
- 通過公式movex=e.targetTouchrs[0].pageX - startx 拿到手指的移動距離
- 將上面的這個距離賦值給 tupian 讓其隨之移動
- 判斷flag是后面的節流閥代碼 當過渡效果未完成不允許拖動
//為tupian添加 touchmove(手指拖動) 事件 拖動 tupiantupian.addEventListener('touchmove', function (e) {//禁止默認行為e.preventDefault()if (flag) {movex = e.targetTouches[0].pageX - startxvar translatex = -num * imgWidth + movex//取消過度tupian.style.transition = 'none'this.style.transform = 'Translatex(' + translatex + 'px)'}})
3.4 為 tupian 添加手指離開DOM事件
事件中:
- 判斷手指的移動有沒有超過50
超過50切換輪播圖
未超50回彈輪播圖- 同時判斷手指滑動方向 決定切換上一張還是下一張輪播圖
- 并且重啟輪播圖
tupian.addEventListener('touchend', function () {/*根據手指的移動距離 判斷是否需要切換輪播圖如果移動距離 >=50 切換輪播圖如果移動距離 <50 回彈輪播圖*///設置節流閥if (flag) {//將節流閥設置為falseflag = falseif (Math.abs(movex) >= 50) {if (movex > 0) {num--} else {num++}var translatex = -num * imgWidth//添加過度效果tupian.style.transition = 'all 1s'this.style.transform = 'Translatex(' + translatex + 'px)'} else {var translatex = -num * imgWidth//添加過度效果tupian.style.transition = 'all 1s'this.style.transform = 'Translatex(' + translatex + 'px)'}//清除定時器clearInterval(timer)//重啟輪播timer = setInterval(function () {num++var translate = -num * imgWidth//設置元素的移動在2s內完成 給元素添加過度tupian.style.transition = 'all 1s'tupian.style.transform = 'TranslateX(' + translate + 'px)'}, 3000)}})
4. 設置指示器的樣式
效果:當輪播圖轉換到相應的圖片是 下面相應的指示器與其他顏色不同
- 設置全局變量sort用來為指示器計數
- 把sort變量放置到transitionend事件中 也就是過度效果完成后sort=圖片的下標值
- 設置指示器效果函數如下兩種:
第一種:將每次調用此函數 將所有的li標簽的類名清空
同時為顯示圖片對應的指示器添加類名 函數調用在transitionend事件中
//設置指示器的樣式function yuan() {for (var i = 0; i < ul.children.length; i++) {ul.children[i].className = ''}//設置對應指示器的樣式ul.children[sort].className = 'aaa'}
第二種:通過classlist屬性 找出具有aaa類名的li將其類名清空 同時為顯示圖片對應的指示器添加類名
函數調用在transitionend事件中
//設置指示器的樣式function yuan() {ul.querySelector('.aaa').classList.remove('aaa')//設置對應指示器的樣式ul.children[sort].className = 'aaa'}
完整代碼:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>*{margin: 0;padding: 0;}.box {position: relative;/* 在移動端如果不設置下面樣式 可以拖動 */overflow: hidden;}.tupian img {float: left;width: 16.66%;}.tupian {width: 600%;margin-left:-414px;}ul {position: absolute;top: 300px;right: 20px;}ul li {float: left;margin-left: 30px;background-color: #fff;display: block;width: 20px;height: 10px;}.aaa {background-color: coral;}</style>
</head><body><div class="box"><div class="tupian"><img src="4.webp" alt=""><img src="1.webp" alt=""><img src="2.webp" alt=""><img src="3.webp" alt=""><img src="4.webp" alt=""><img src="1.webp" alt=""></div><ul><li data-aa="0" class="aaa"></li><li data-aa="1"></li><li data-aa="2"></li><li data-aa="3"></li></ul></div>
</body>
<script>var box = document.querySelector('.box')var tupian = document.querySelector('.tupian')var ul = document.querySelector('ul')//獲取移動的寬度var imgWidth = box.offsetWidth//創建變量 用于輪播圖的計數器var num = 0//創建一個用于指示器的計數器var sort = 0//設置節流閥flag = true//創建指示器的計數器var sort=0//自動輪播效果的實現var timer = setInterval(function () {num++var translate = -num * imgWidth//設置元素的移動在2s內完成 給元素添加過度tupian.style.transition = 'all 1s'tupian.style.transform = 'TranslateX(' + translate + 'px)'}, 3000)//過度執行結束后 會觸發 transitionend 事件tupian.addEventListener('transitionend', function () {// console.log(num)if (num == 4) {num = 0//取消過度tupian.style.transition = 'none'tupian.style.transform = 'TranslateX(0px)'}else if(num<0){num=3var translatex=-num*imgWidthtupian.style.transition = 'none'tupian.style.transform = 'TranslateX('+translatex+'px)'}//為節流閥設置為trueflag = true//設置指示器樣式sort=numyuan()})/*實現手指拖動輪播圖(1手指觸摸到元素上 停止輪播圖自動播放(2判斷手指的移動方向 然后圖片向這個方向移動(3判斷手指的移動距離 如果超出范圍就切換輪播圖 如果沒有超出這個范圍 則繼續顯示原來的輪播圖*///獲取手指的初始坐標var startx = 0//獲取圖片的初始坐標var tupianx = 0//手指的移動距離var movex = 0//為tupian添加 touchstart(手指觸摸) 事件 停止輪播tupian.addEventListener('touchstart', function (e) {//手指按下時將現在坐標賦值給 startxstartx = e.targetTouches[0].pageXtupianx = tupian.offsetLeft//清除定時器clearInterval(timer)timer = null})//為tupian添加 touchmove(手指拖動) 事件 拖動 tupiantupian.addEventListener('touchmove', function (e) {//禁止默認行為e.preventDefault()if (flag) {movex = e.targetTouches[0].pageX - startxvar translatex = -num * imgWidth + movex//取消過度tupian.style.transition = 'none'this.style.transform = 'Translatex(' + translatex + 'px)'}})//為tupian添加 touchend(手指離開) 事件 重啟輪播tupian.addEventListener('touchend', function () {/*根據手指的移動距離 判斷是否需要切換輪播圖如果移動距離 >=50 切換輪播圖如果移動距離 <50 回彈輪播圖*///設置節流閥if (flag) {//將節流閥設置為falseflag = falseif (Math.abs(movex) >= 50) {if (movex > 0) {num--} else {num++}var translatex = -num * imgWidth//添加過度效果tupian.style.transition = 'all 1s'this.style.transform = 'Translatex(' + translatex + 'px)'} else {var translatex = -num * imgWidth//添加過度效果tupian.style.transition = 'all 1s'this.style.transform = 'Translatex(' + translatex + 'px)'}//清除定時器clearInterval(timer)//重啟輪播timer = setInterval(function () {num++var translate = -num * imgWidth//設置元素的移動在2s內完成 給元素添加過度tupian.style.transition = 'all 1s'tupian.style.transform = 'TranslateX(' + translate + 'px)'}, 3000)}})//設置指示器的樣式function yuan() {for (var i = 0; i < ul.children.length; i++) {ul.children[i].className = ''}//設置對應指示器的樣式ul.children[sort].className = 'aaa'}
</script></html>