当先锋百科网

首页 1 2 3 4 5 6 7

思路

无缝切换

假设这是图片数组[0,1,2,3,4] 共5张图片,index是4的时候点击下一张,要切换成第1张,而不是从4->3->2->1->0这样滚回去,也就是说其实是这样的效果 [0,1,2,3,4,0] 实现4->0的无缝切换。
从0->4也是同样的道理,0在点击上一张的时候,瞬间切换到4后面的0,然后再切换到4.

节流

防抖简单来说就是打断回城,需要重新回城,
节流就是cd。
当最后一张图片切换到第一张图片时,快速点击会出现闪屏的现象,因此可以限制点击速率来实现。 设置一个lock变量,点击后值设置为false,在点击xx毫秒后再设置true。使用setTimeout实现

代码

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>轮播图</title>
</head>
<body>
    <!-- 容器 -->
    <div class="box">
        <!-- 图片列表 -->
        <div class="img-list">
            <img src="pic/1.png" alt="">
            <img src="pic/2.png" alt="">
            <img src="pic/3.png" alt="">
            <img src="pic/4.png" alt="">
            <img src="pic/5.png" alt="">
        </div>
        <!-- 小箭头 -->
        <div class="arrow">
            <a href="javascript:;" class="left"><</a>
            <a href="javascript:;" class="right">></a>
        </div>
        <!-- 小圆点 -->
        <ul class="circle-list">
            <li class="circle" data-n="0"></li>
            <li class="circle" data-n="1"></li>
            <li class="circle" data-n="2"></li>
            <li class="circle" data-n="3"></li>
            <li class="circle" data-n="4"></li>
        </ul>
    </div>
    <script src="./main.js"></script>
</body>
</html>

css

* {
    margin: 0;
    padding: 0;
}

ul {
    list-style: none;
}

.box {
    overflow: hidden;
    position: relative;
    width: 1024px;
    height: 580px;
    margin: 100px auto 0;
}

.box .img-list {
    display: flex;
    position: relative;
    left: 0px;
    width: 100%;
    height: 100%;
    transition: 0.5s ease;
}

.box .img-list img {
    width: 100%;
    cursor: pointer;
}

.box a {
    position: absolute;
    top: 50%;
    transform: translate(0,-50%);
    display: block;
    width: 40px;
    height: 70px;
    background: rgba(0,0,0,0.7);
    color: white;
    user-select: none;
    font-size: 30px;
    text-align: center;
    line-height: 70px;
    text-decoration: none;
}

.box a.left {
    left: 0;
}

.box a.right {
    right: 0;
}

.circle-list {
    display: flex;
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translate(-30%,0);
    width: 240px;
    height: 40px;
    z-index: 99;
}

.circle-list li{
    cursor: pointer;
}

.circle-list > .circle {
    margin: 0 5px;
    width: 25px;
    height: 25px;
    background-color: #ecf0f1;
    border-radius: 50%;
}

.circle-list > .circle.active {
    /* background-color: #154599; */
    background-color: #e74c3c;
}

javascript

// 如何实现?
// 1.最外层盒子包裹
// 2.图片移动动画
// 3.点击事件
// 4.小圆点

// 获取左右按钮和图片列表
let btnLeft = document.querySelector('.left');
let btnRight = document.querySelector('.right');
let imgList = document.querySelector('.img-list');
// 图片索引
let index = 0;
// 复制第一张图片到最后面
let cloneFirstImg = imgList.firstElementChild.cloneNode();
imgList.appendChild(cloneFirstImg);
// 获取小圆点的数组
const circles = document.querySelectorAll('.circle');
// 设置函数节流锁
let lock = true;
// 小圆点点击切换图片  使用事件代理
const oCircle = document.querySelector('.circle-list');
// 自动轮播
let autoPlay =  setInterval(setRightGo, 2000);
// 获取轮播图的区域
const obox = document.querySelector('.box');
// 首次添加小圆点
setCircles();

// 往右切换下一张
function setRightGo() {
    if(!lock) return;
    index++;
    imgList.style.left = index * -1024 + 'px';
    // 加回过度效果
    imgList.style.transition = '0.5s ease';
    // 也就是 下一张是 '第一张'
    if(index===5) {
        index = 0;
        setTimeout(() => {
            imgList.style.left = 0;
            imgList.style.transition = 'none';
        // 这里是因为过度动画是0.5s 所以这里也是0.5s,相当于藏起来    
        },500);
    }
    // 设置小圆点高亮
    setCircles();
    // 关锁
    lock = false;
    setTimeout(() => {
        lock = true;
    },500);
}

// 右按钮
btnRight.addEventListener('click',setRightGo);

// 左按钮也是一样
btnLeft.addEventListener('click',(e) => {
    if(!lock) return;
    index--;
    if(index === -1) {
        // 首先 瞬间切换到第六张假图、也就是伪装的第一张图片
        // 并且不需要过度动画
        imgList.style.left = 5 * -1024 + 'px';
        imgList.style.transition = 'none';
        index = 4;
        // 然后进行异步操作,然后过渡到第五张
        setTimeout(() => {
            imgList.style.left = index * -1024 + 'px';
            // 加上动画
            imgList.style.transition = '0.5s ease';
        },0);
    }else {
        imgList.style.left = index * -1024 + 'px';
    }
    // 设置小圆点高亮
    setCircles();
    // 关锁
    lock = false;
    setTimeout(() => {
        lock = true;
    }, 500);
})


// 小圆点高亮显示
function setCircles() {
    for (let i=0;i<circles.length;i++) {
        if(i === index) {
            circles[i].classList.add('active');
        }else {
            circles[i].classList.remove('active');
        }
    }
}


oCircle.addEventListener('click',(e) => {
    if(e.target.nodeName.toLowerCase() === 'li') {
        // 当前元素的 data-n 的值
        const n = (Number(e.target.getAttribute('data-n')));
        index = n;
        imgList.style.left = index * -1024 + 'px';
        setCircles();
    }
})


// 移入关闭定时器
obox.addEventListener('mouseenter',() => {
    clearInterval(autoPlay);
})
// 移出开启定时器
obox.addEventListener('mouseleave',() => {
    // 设表先关,设置定时器前,先清除
    clearInterval(autoPlay);
    autoPlay = setInterval(setRightGo, 2000);
})

参考视频: https://www.bilibili.com/video/BV1My4y1U79h?p=1