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=3
var translatex=-num*imgWidth
tupian.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) {
//手指按下时将现在坐标赋值给 startx
startx = e.targetTouches[0].pageX
tupianx = tupian.offsetLeft
//清除定时器
clearInterval(timer)
timer = null
})
3.3 为 tupian 添加手指在DOM上的移动事件
事件中:
- 通过e.targetTouchrs[0].pageX不断获取手指的坐标
- 通过公式movex=e.targetTouchrs[0].pageX - startx 拿到手指的移动距离
- 将上面的这个距离赋值给 tupian 让其随之移动
- 判断flag是后面的节流阀代码 当过渡效果未完成不允许拖动
//为tupian添加 touchmove(手指拖动) 事件 拖动 tupian
tupian.addEventListener('touchmove', function (e) {
//禁止默认行为
e.preventDefault()
if (flag) {
movex = e.targetTouches[0].pageX - startx
var 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) {
//将节流阀设置为false
flag = false
if (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=3
var translatex=-num*imgWidth
tupian.style.transition = 'none'
tupian.style.transform = 'TranslateX('+translatex+'px)'
}
//为节流阀设置为true
flag = true
//设置指示器样式
sort=num
yuan()
})
/*
实现手指拖动轮播图
(1手指触摸到元素上 停止轮播图自动播放
(2判断手指的移动方向 然后图片向这个方向移动
(3判断手指的移动距离 如果超出范围就切换轮播图 如果没有超出这个范围 则继续显示原来的轮播图
*/
//获取手指的初始坐标
var startx = 0
//获取图片的初始坐标
var tupianx = 0
//手指的移动距离
var movex = 0
//为tupian添加 touchstart(手指触摸) 事件 停止轮播
tupian.addEventListener('touchstart', function (e) {
//手指按下时将现在坐标赋值给 startx
startx = e.targetTouches[0].pageX
tupianx = tupian.offsetLeft
//清除定时器
clearInterval(timer)
timer = null
})
//为tupian添加 touchmove(手指拖动) 事件 拖动 tupian
tupian.addEventListener('touchmove', function (e) {
//禁止默认行为
e.preventDefault()
if (flag) {
movex = e.targetTouches[0].pageX - startx
var translatex = -num * imgWidth + movex
//取消过度
tupian.style.transition = 'none'
this.style.transform = 'Translatex(' + translatex + 'px)'
}
})
//为tupian添加 touchend(手指离开) 事件 重启轮播
tupian.addEventListener('touchend', function () {
/*
根据手指的移动距离 判断是否需要切换轮播图
如果移动距离 >=50 切换轮播图
如果移动距离 <50 回弹轮播图
*/
//设置节流阀
if (flag) {
//将节流阀设置为false
flag = false
if (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>