写一个轮播图大概分为以下几步:
(0.获取索引小圆点)
1.制作辅助图(前后各复制一个图片,将最后一张放在最前面(appendChild(节点)),将第一张插入到最后面使用insertBefore(节点,位置))
2.开启一个定时器(setInterval)
3.定时器里面有个方法是设置正确的位置(setRightPosition)
4.设置正确的位置方法里面包含1.设置位置(setPosition) 2.检查位置(checkPosition) 两个方法
5.给小圆点添加颜色可以放在检查位置的后面,等检查完位置也就是校正索引后设置小圆点颜色
移动端可以添加手指的touchstart,touchmove,touchend三个方法
其中在touchstart中停止定时器,判断当前是否正在滑动,如果是就return,如果不是就获取手指刚接触的位置也就是起始位置
在touchmove中获取手指滑动当前X轴的位置currentX = e.touches[0].pageX 获取起始位置与当前位置的距离 this.distance = currentX - this.startX 获取起始位置时候的距离 也就是设置位置时的位置let startPosition = -this.currentIndex * this.sliderWidth 用起始位置加上移动距离 再设置位置 let currentPosition = startPosition + this.distance this.setPosition(currentPosition)即可达到一个页面随手指滑动的效果
在touchend中, 获取手指滑动距离的绝对值 let currentMove = Math.abs(this.distance);
因为设置位置时都是根据索引设置的,所以我们要改变的只是索引的位置,然后设置正确的位置最后开启定时器即可
if (currentMove == 0) return
else if ((this.distance > 0) && (currentMove > (this.sliderWidth * 0.25))) {
this.currentIndex–
} else if ((this.distance < 0) && (currentMove > (this.sliderWidth * 0.25))) {
this.currentIndex++
}
this.setRightPosition(-this.currentIndex * this.sliderWidth)
this.startTimeout()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图制作</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="swiper">
<ul class="clearfix">
<li><img src="./images/1.jpg" alt=""></li>
<li><img src="./images/2.jpg" alt=""></li>
<li><img src="./images/3.jpg" alt=""></li>
<li><img src="./images/4.jpg" alt=""></li>
<li><img src="./images/5.jpg" alt=""></li>
</ul>
<div class="left-box">
<span><</span>
</div>
<div class="right-box">
<span>></span>
</div>
<div class="index-box">
<ol></ol>
</div>
</div>
<script src="./index.js"></script>
<script>
const slider = new Slider(".swiper")
</script>
</body>
</html>
class Slider {
constructor(cls) {
// 拿到父盒子容器也就是视口大小
this.box = document.querySelector(cls)
// ul标签也是图片的直接父盒子
this.picBox = this.box.querySelector("ul")
// 索引盒子
this.indexBox = this.box.querySelector(".index-box")
// 左侧箭头
this.leftBox = this.box.querySelector(".left-box")
// 右侧箭头
this.rightBox = this.box.querySelector(".right-box")
// 图片的张数
this.picNum = this.picBox.children.length
// 当前索引,默认为1
this.currentIndex = 1
// 视口宽度
this.sliderWidth = this.box.offsetWidth
// 轮播延时
this.delay = 3000
// transition延时
this.animateTime = 300
// 定时器句柄
this.timer = null
// 当前是否在滑动
this.scrolling = false
this.init()
}
init() {
this.pointInit()
this.eventInit()
this.copyPic()
this.startTimeout()
}
next() {
this.endTimeout()
this.currentIndex++
this.setRightPosition(-this.currentIndex * this.sliderWidth)
this.startTimeout()
}
previous() {
this.endTimeout()
this.currentIndex--
this.setRightPosition(-this.currentIndex * this.sliderWidth)
this.startTimeout()
}
touchStart(e) {
if (this.scrolling) return
// 关闭定时器
this.endTimeout()
// 获取触摸起始位置
this.startX = e.touches[0].pageX;
}
touchMove(e) {
// 当前触摸的x轴位置
let currentX = e.touches[0].pageX
// 触摸一共移动x轴距离
this.distance = currentX - this.startX
// 获取触摸起始位置
let startPosition = -this.currentIndex * this.sliderWidth
// 当前拖拽触摸的位置
let currentPosition = startPosition + this.distance
// 实时变化
this.setPosition(currentPosition)
}
touchEnd() {
// 1.获取移动的距离
let currentMove = Math.abs(this.distance);
if (currentMove == 0) return
else if ((this.distance > 0) && (currentMove > (this.sliderWidth * 0.25))) {
this.currentIndex--
} else if ((this.distance < 0) && (currentMove > (this.sliderWidth * 0.25))) {
this.currentIndex++
}
// 设置正确的位置
this.setRightPosition(-this.currentIndex * this.sliderWidth)
// 开启定时器
this.startTimeout()
}
// 节流函数
throttle(fun) {
let time = 0
let that = this
return function() {
let now = Date.now()
if ((now - time) > 500) {
fun.call(that)
time = now
}
}
}
// 闭包执行函数
eventInit() {
const next = this.throttle(this.next)
const previous = this.throttle(this.previous)
this.leftBox.addEventListener("click", () => {
previous()
})
this.rightBox.addEventListener("click", () => {
next()
})
this.picBox.addEventListener("touchstart", (e) => {
this.touchStart(e)
})
this.picBox.addEventListener("touchmove", (e) => {
this.touchMove(e)
})
this.picBox.addEventListener("touchend", (e) => {
this.touchEnd(e)
})
}
startTimeout() {
this.timer = setInterval(() => {
this.currentIndex++;
this.setRightPosition(-this.currentIndex * this.sliderWidth)
}, this.delay);
}
endTimeout() {
clearInterval(this.timer)
}
setPointColor() {
let num = this.indexBox.children[0].children.length
for (let i = 0; i < num; i++) {
this.indexBox.children[0].children[i].classList.remove("active")
}
this.indexBox.children[0].children[this.currentIndex - 1].classList.add("active")
}
pointInit() {
// 自动创建小圆点
for (let i = 0; i < this.picNum; i++) {
let li = document.createElement("li")
this.indexBox.children[0].appendChild(li)
}
this.indexBox.children[0].children[0].classList.add("active")
this.indexBox.children[0].style.width = this.indexBox.children[0].children.length * 10 * 2 + "px"
Array.prototype.forEach.call(this.indexBox.children[0].children, (item, index) => {
item.addEventListener("click", () => {
if (this.scrolling == true) return
else {
this.currentIndex = index + 1
this.setPosition(-this.currentIndex * this.sliderWidth)
this.checkPosition()
}
})
item.addEventListener("mouseleave", () => {
this.startTimeout()
})
item.addEventListener("mouseenter", () => {
this.endTimeout()
})
})
}
//复制图片,形成辅助图
copyPic() {
if (this.picNum > 1) {
let firstPic = this.picBox.children[0].cloneNode(true)
let lastPic = this.picBox.children[this.picNum - 1].cloneNode(true)
this.picBox.appendChild(firstPic)
this.picBox.insertBefore(lastPic, this.picBox.children[0])
}
this.picBox.style.width = (this.sliderWidth * this.picBox.children.length) + "px"
this.setPosition(-this.sliderWidth)
}
//设置正确的位置,主要逻辑是先设置位置然后判断位置是否正确
setRightPosition(position) {
// 是否正在滚动
this.scrolling = true
this.picBox.style.transition = `left ${this.animateTime}ms`
// 设置位置
this.setPosition(position)
// 检查当前位置是否正确
this.checkPosition()
// 结束正在滚动
this.scrolling = false
}
//设置图片位置
setPosition(offset) {
this.picBox.style.left = `${offset}px`
}
//检查当前的位置设置是否正确
checkPosition() {
setTimeout(() => {
// 清除偷梁换柱动画的300ms过渡,否则会看出跳转
this.picBox.style.transition = "0ms"
if (this.currentIndex == 0) {
this.currentIndex = this.picNum
this.setPosition(-this.currentIndex * this.sliderWidth)
}
if (this.currentIndex == this.picNum + 1) {
this.currentIndex = 1
this.setPosition(-this.currentIndex * this.sliderWidth)
}
//设置小圆点颜色
this.setPointColor()
}, this.animateTime);
//必须要加上定时器,否则直接执行将300ms延时覆盖掉,这里的延时必须设置为与动画时长相同的
// 因为当动画执行完之后才进行偷梁换柱,否则动画不会执行,就直接偷梁换柱了
}
}