<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>js无限轮播简单版实现</title>
<style type="text/css">
* { margin: 0; padding: 0; box-sizing: border-box;}
.container { overflow: hidden; margin: 100px; position: relative; }
.slide-box { display: flex; position: relative; }
.slide-item { display: flex; align-items: center; justify-content: center; font-size: 48px; color: #fff;}
.slide-item.red { background-color: red; }
.slide-item.orange { background-color: orange; }
.slide-item.blue { background-color: blue; }
.slide-item.purple { background-color: purple; }
.slide-item.pink { background-color: pink; }
.btns a {
display: none;
width: 40px;
height: 40px;
line-height: 40px;
background: rgba(0,0,0,0.3);
color: #fff;
position: absolute;
cursor: pointer;
top: 50%;
margin-top: -20px;
text-align: center;
}
.btns a.pre {
left: 10px;
}
.btns a.next {
right: 10px;
}
.btns a:hover {
background: rgba(0,0,0,0.7);
}
.container:hover .btns a {
display: block;
}
.dots {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
font-size: 0;
}
.dots span {
display: inline-block;
width: 10px;
height: 10px;
background: #ccc;
border: 2px solid #999;
border-radius: 50%;
margin: 4px;
cursor: pointer;
}
.dots span.on {
background: #333;
border-color: #fff;
}
</style>
</head>
<body>
<div class="container">
<div class="slide-box">
<div class="slide-item red">1</div>
<div class="slide-item orange">2</div>
<div class="slide-item blue">3</div>
<div class="slide-item purple">4</div>
<div class="slide-item pink">5</div>
</div>
<div class="btns">
<a class="pre">pre</a>
<a class="next">next</a>
</div>
<div class="dots">
<!-- <span class="on"></span>
<span></span>
<span></span>
<span></span>
<span></span> -->
</div>
</div>
<script>
/*
t 切换一屏需要的时间
interval 屏切换时分多少次来修改left的值(使效果看起来像动画,不那么生硬)
itemW 每一屏的宽度
itemH 每一屏的高度
animating 屏正在切换动画中
timer 自动轮播的定时器
*/
let t = 400, interval = 20, itemW = 500, itemH = 300, animating = false, timer = null,
container = document.querySelector('.container'), // 最外层容器
slideBox = document.querySelector('.slide-box'), // 滚动项的外包裹层
slideItems = slideBox.children
let dots = document.querySelector('.dots') // 最下面的指示器
slideBox.prepend(slideItems[slideItems.length-1].cloneNode(true)) // 因为要做无限滚动,在最前面复制一份最后屏,在最后页复制一份第一屏
slideBox.appendChild(slideItems[1].cloneNode(true))
let len = slideItems.length - 2, index = 1
let boxWidth = 0
for(let i=0; i<slideItems.length; i++) { // 遍历每一项,设置宽度和高度
let item = slideItems[i]
item.style.width = itemW + 'px'
item.style.height = itemH + 'px'
boxWidth += itemW
}
slideBox.style.width = boxWidth + 'px' // 给图片包裹层设置宽度
container.style.width = itemW + 'px' // 给最外层容器设置宽度
slideBox.style.left = (index*itemW * -1) + 'px' // 设置初始时slide-box的 left值
let btnPre = document.querySelector('.btns .pre')
let btnNext = document.querySelector('.btns .next')
btnPre.onclick = function() {
if(animating) return
if(index === 1) {
index = len
} else {
index -= 1
}
slide(itemW)
}
btnNext.onclick = function() {
if(animating) return
if(index === len) {
index = 1
} else {
index += 1
}
slide(itemW * -1)
}
initDots() // 初始化轮播图下面的指示器
function initDots() {
for(let i =1; i<=len; i++) {
let span = document.createElement('span')
span.setAttribute('data-index',i)
if(index === i) {
span.classList = 'on'
}
dots.appendChild(span)
span.onclick = function() {
if(animating) return
let dIndex = this.getAttribute('data-index') * 1 // 注意这里要转换成数值
let scrollPx = 0
if(dIndex === index) {
return
}
if(dIndex > index) { // 点击的是当前活动图片的后面的图片, left值应该是变小
scrollPx = (dIndex - index) * itemW * -1
}
if(dIndex < index) { // 点击的是当前活动图片的前面的图片, left值应该是变大
scrollPx = (dIndex - index) * itemW * -1
}
index = dIndex
slide(scrollPx)
}
}
}
function activeDot() { // 使指定索引的提示器高亮
let spans = [...dots.querySelectorAll('span')]
spans.forEach(s => s.setAttribute('class',''))
spans[index-1].classList = 'on'
}
function slide(scrollPx) { // scrollPx 要滚动多少px
if(scrollPx === 0) return
let speed = scrollPx/(t/interval)
let left = parseInt(slideBox.style.left)+ scrollPx // 最终的left
animating = true
function go() {
// 1. 如果是向前滚(next), speed的值是负数, 当speed<0 并且当前slideBox的left值大于最终的left值
if( (speed > 0 && parseInt(slideBox.style.left)< left) || (speed < 0 && parseInt(slideBox.style.left) > left)) {
slideBox.style.left = parseInt(slideBox.style.left) + speed + 'px'
setTimeout(go, interval)
} else {
slideBox.style.left = left + 'px'
if(left> -1 * itemW) { // 如果是第一张,再往前滚,滚完后将left值设置成最后一张的 left
slideBox.style.left = -1 * itemW * len + 'px'
}
if(left < -1 * itemW * len) { // 如果是最后一张,再往后滚,滚完后将left值设置成第一张的 left
slideBox.style.left = -1 * itemW + 'px'
}
animating = false // 动画完成
}
}
go()
activeDot()
}
function autoPlay() { // 自动轮播
timer = !timer && setInterval(function() {
btnNext.onclick()
}, 3000)
}
function stopPlay() {
clearInterval(timer)
timer = null
}
container.onmouseover = stopPlay // 鼠标滑过时停止自动轮播
container.onmouseout = autoPlay // 鼠标移开时自动轮播
autoPlay() // js代码完成后调用一次自动轮播
</script>
</body>
</html>
效果:
scroll.gif
网友评论