废话不多说,直接上代码(注:js部分代码会有截图对其解释)
一、HTML
<div class="bigBox">
<!-- 轮播主体 -->
<div class="box">
<div class="littleBox">1</div>
<div class="littleBox">2</div>
<div class="littleBox">3</div>
</div>
<!-- 底部小点 -->
<div class="point">
<div class="active"></div>
<div></div>
<div></div>
</div>
<!-- 上一页 -->
<div class="prev"></div>
<!-- 下一页 -->
<div class="next"></div>
</div>
二、CSS
* {
margin: 0;
padding: 0;
}
.bigBox {
width: 300px;
height: 180px;
border: 2px solid black;
overflow: hidden;
margin: 100px auto;
position: relative;
}
/* 轮播主体 */
.box {
width: 900px;
display: flex;
transition: all .6s;
}
.littleBox {
text-align: center;
line-height: 180px;
width: 300px;
height: 180px;
}
.littleBox:nth-of-type(1) {
background-color: skyblue;
}
.littleBox:nth-of-type(2) {
background-color: pink;
}
.littleBox:nth-of-type(3) {
background-color: yellow;
}
/* 小点 */
.point {
position: absolute;
width: 50px;
height: 10px;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: space-evenly;
cursor: pointer;
}
.point div {
width: 10px;
height: 10px;
background-color: rgb(151, 151, 151);
border-radius: 10px;
}
.point .active {
background-color: white;
}
/* 上一页/下一页 */
.prev::after,
.next::after {
position: absolute;
width: 20px;
height: 30px;
top: 50%;
transform: translateY(-50%);
background-color: aliceblue;
line-height: 30px;
text-align: center;
cursor: pointer;
}
/* 上一页 */
.prev::after {
content: '<';
left: 0;
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
/* 下一页 */
.next::after {
content: '>';
right: 0;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
}
三、JS以及解释截图
// dom元素
const doms = {
box: document.querySelector('.box'),
point: document.querySelectorAll('.point div'),
prev: document.querySelector('.prev'),
next: document.querySelector('.next')
}
// 当前所在页面(从0开始)
let currentIndex = 0
// 切换页面
function moved(index) {
currentIndex = index
const x = -300 * index
doms.point.forEach((item, i) => {
item.classList.remove('active')
})
doms.point[index].classList.add('active')
doms.box.style.transform = `translateX(${x}px)`
}
// 上一页点击事件
function changePrev() {
currentIndex === 0 ? currentIndex = 2 : currentIndex--
moved(currentIndex)
}
doms.prev.addEventListener('click', changePrev)
// 下一页点击事件
function changeNext() {
currentIndex === 2 ? currentIndex = 0 : currentIndex++
moved(currentIndex)
}
doms.next.addEventListener('click', changeNext)
// 小点点击事件
doms.point.forEach((item, i) => {
item.addEventListener('click', function () {
moved(i)
})
})
// 自动轮播
let timer = setInterval(changeNext, 2000)
// 鼠标移入后清除自动轮播
doms.box.addEventListener('mouseenter', function () {
clearInterval(timer)
})
// box元素相对视口的位置
const boxPosition = {
x: Math.floor(doms.box.getBoundingClientRect().x),
y: Math.floor(doms.box.getBoundingClientRect().y)
}
// 鼠标最初位置
let mouseX = 0
// box移动的位置
let transformX = 0
let x = 0
// 手动拖拽
function onMoueseDown(e) {
mouseX = e.clientX - boxPosition.x
doms.box.addEventListener('mousemove', onMoueseMove)
}
function onMoueseMove(e) {
e.preventDefault()
x = transformX + -1 * (mouseX - (e.clientX - boxPosition.x));
doms.box.style.transform = `translateX(${x}px)`
}
function onMoueseUp() {
// 判断当前页数
if (Math.round(-1 * x / 300) < 0) {
currentIndex = 2
} else if (Math.round(-1 * x / 300) > 2) {
currentIndex = 0
} else {
currentIndex = Math.round(-1 * x / 300)
}
transformX = currentIndex * -300
moved(currentIndex)
// 移出监听
doms.box.removeEventListener('mousemove', onMoueseMove)
}
function onMoueseLeave() {
// 移出监听
doms.box.removeEventListener('mousemove', onMoueseMove)
// 添加自动轮播
timer = setInterval(changeNext, 2000)
}
// 鼠标按下添加拖拽
doms.box.addEventListener('mousedown', onMoueseDown)
// 鼠标抬起移除事件
doms.box.addEventListener('mouseup', onMoueseUp)
// 鼠标移出后添加自动轮播以及移出事件
doms.box.addEventListener('mouseleave', onMoueseLeave)
解释截图(最左侧为可视窗口最左侧):