前言

先奉上本文需要的所有资源,免费下载,代码有详细注释,可搭配本文使用:

前端JavaScript实现轮播图效果

百度网盘:百度网盘 请输入提取码

提取码:slbt

没有添加动画效果,添加了自动切换和手动切换功能。

效果演示

 功能介绍

  • 页面加载后,每隔两秒就切换下一张图片

  • 点击上一张和下一张按钮可以循环切换

  • 点击小圆点可以指定切换

  • 鼠标放在图片上停止切换,移开后等待两秒继续自动切换

关键功能由定时器实现,如果对定时器不了解的朋友,可以看看我之前写的文章:

JavaScript中的定时器详解

我们将本案例拆分成三个部分来讲解。

HTML

HTML 部分比较简单,直接由注释来讲解:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图效果</title>
    <!-- 引入外部样式文件 -->
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <!-- 大容器 -->
    <div class="slideshow">
        <!-- 图片展示 -->
        <div class="image">
            <!-- 通过js改变src属性值替换图片 -->
            <img src="./image/1.png" id="img-show">
        </div>
        <!-- 上一张按钮 -->
        <div class="previous" id="to-pre">❮</div>
        <!-- 下一张按钮 -->
        <div class="next" id="to-next">❯</div>
        <!-- 自由选择小圆点 -->
        <div class="dots" id="dot-container">
            <!-- 小圆点由 js 动态生成 -->
        </div>
    </div>
    <!-- 引入外部脚本文件 -->
    <script src="./slide.js"></script>
</body>
</html>

CSS

CSS 部分也比较简单,直接由注释来讲解:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    background-color: rgb(254, 202, 211);
}
​
/* 大容器实现水平垂直居中 */
.slideshow {
    position: absolute; /* 绝对定位 */
    top: 50%;           /* 向下偏移窗口高度的50% */
    left: 50%;          /* 向右偏移窗口长度的50% */
    width: 700px;
    /* 
    由于上面的偏移位置是由当前元素的左上角决定,注释下面一句代码查看会发生什么问题,
    下面这句代码是以当前元素的宽高向上向左移动50%,联合上面的偏移实现水平垂直居中。
    */
    transform: translate(-50%, -50%);
}
​
.slideshow .image {
    width: 100%;
}
.slideshow .image>img {
    display: block; /* 去除图片底部的空白 */
    width: 100%;    /* 让图片的宽始终的等于父元素的宽 */
}
​
/* 切换按钮 */
.slideshow .previous,
.slideshow .next {
    position: absolute;
    /* 下面两句实现切换按钮垂直居中 */
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    margin-left: 5px;
    border-radius: 20px;
    background-color: rgba(0, 0, 0, 0.5);
    font: 700 20px/2 "Arial";
    color: white;
    text-align: center;
}
.slideshow .next {
    right: 5px; /* 将下一张按钮移到右边 */
}
.slideshow .previous:hover,
.slideshow .next:hover {
    cursor: pointer;
    background-color: rgba(0, 0, 0, 0.7);
}
​
/* 放置小圆点的容器,不给它设置宽度,让它可以动态添加小圆点 */
.slideshow .dots {
    position: absolute;
    bottom: 20px;   /* 从底部向上偏移20px */
    /* 下面两句让小圆点容器实现水平居中 */
    left: 50%;
    transform: translateX(-50%);
}
.slideshow .dots:hover {
    cursor: pointer;
}
​
/* 小圆点样式 */
.dot {
    display: inline-block;
    width: 16px;
    height: 16px;
    margin: 0px 4px;
    border-radius: 8px;
    background-color: white;
}
.dot:hover {
    cursor: pointer;
    background-color: rgb(72, 72, 72);
}
/* 小圆点对应的图片被展示时,小圆点变灰 */
.dots .selected {
    background-color: rgb(72, 72, 72);
}

JavaScript

轮播图的实现关键就在于 JavaScript 代码,下面详细介绍这一部分,建议对照源文件的代码!

生成小圆点

首先,需要获取所有图片的路径。这里把路径存入数组中,之后可以根据数组的长度来动态的创建小圆点:

const images = ['./image/1.png', './image/2.jpg', './image/3.jpg', './image/4.jpg', './image/5.jpg', './image/6.png'];

利用这个数组来动态的创建小圆点,在这之前,需要先获得容纳小圆点的容器:

let dotContainer = document.getElementById("dot-container");
// 根据数组images的长度获取图片张数,并动态创建小圆点
for(let i=0; i<images.length; i++) {
    let dot = document.createElement("span");   // 创建小圆点
    dot.className = "dot";  // 为创建的小圆点设置类名
    dot.id = "dot"+i;       // 为创建的小圆点设置id
    // 将创建的小圆点添加到小圆点容器中
    dotContainer.appendChild(dot);
}

完成上述代码后,底部会出现多个小圆点,效果如下:

 第一张图片出现时,它所对应的小圆点应该会变成灰色。要实现这种效果,可以加入下面一段代码:

let defaultDot = document.getElementById("dot0").className = "dot selected";

这句话出现在全局作用域中,因此页面加载时,第一张图片的小圆点就会变成灰色。通过改变元素的类属性值实现!

当所有小圆点都被创建后,我们需要通过类名获取它们,之后你便会知道为什么这么做:

let dots = document.getElementsByClassName("dot");

接下来要用到定时器,因为我们要实现自动切换效果。

自动切换

页面加载后,我们让图片每隔两秒切换一次,于是需要在全局作用域中添加一个定时器。用变量 t 来保存定时任务的标识符,t 需要在全局作用域中添加:

t = setTimeout( ()=>{ 
    timer();
}, 1000*2);
timer() 是我们自己定义的一个函数,这是它内部的代码:

function timer() {
    changeImage(false); // 调用图片切换函数
    // 图片切换后重新设置一个定时器
    t = setTimeout( ()=>{ timer(); }, 1000*2);
}

页面加载到定时器时,定时器会在两秒后执行回调函数。接下来回调函数中的 timer() 函数会被执行,在 timer() 内部,图片切换函数会被调用,调用完成后再重新设置一个定时器。因为 setTimeout() 是一次性的,页面加载时的定时器已经结束了,所以需要重新创建定时器。而重新创建的定时器又会调用自身所在的函数,于是每隔两秒会进入一次循环。如果有不理解的朋友,建议先去了解一下定时器。

我们再看看图片切换函数是什么样的,这个函数也会被前后切换按钮调用,通过判断传入的是 true 还是 false 来执行前后切换。还记得前面说过当所有小圆点都被创建后,我们需要通过类名获取它们,获取它们后,我们就可以通过索引的方式访问我们想访问的那个小圆点,在更改小圆点样式的时候非常有用。这里的 imgNow 是一个全局变量,记得在全局作用域中添加这个变量,用来标记当前展示的是第几张图片:

// 图片切换函数,传入布尔值,true:前一张, false:后一张
function changeImage(direction) {
    // 先通过循环让所有小圆点样式恢复初始值(白色)
    for(let i=0; i<dots.length; i++) {
        dots[i].className = "dot";
    }
    // 判断是向前切换还是向后切换
    if(direction) {
        if(imgNow == 0) {
            // 如果是第一张继续向前切换,则被切换到最后一张形成循环
            imgNow = images.length-1;
        } else {
            imgNow -= 1;
        }
        // 切换图片
        document.getElementById("img-show").src = images[imgNow]; 
        // 将当前图片的小圆点变灰
        dots[imgNow].className = "dot selected";
    } else {
        if(imgNow == images.length-1) {
            // 如果是最后一张继续向后切换,则被切换到第一张形成循环
            imgNow = 0;
        } else {
            imgNow += 1;
        }
        document.getElementById("img-show").src = images[imgNow];
        dots[imgNow].className = "dot selected";
    }
}

以上所有代码就已经实现了文章开头演示的效果。

前后切换

接下来实现前后按钮切换效果,我们需要给这两个按钮添加事件监听器:

let previous = document.getElementById("to-pre");
previous.addEventListener("click", function() { 
    clearTimeout(t);    // 先清除定时器
    changeImage(true);  // true 向前切换图片
    t = setTimeout( ()=>{ timer(); }, 1000*2);    // 重新创建一个定时器
});
let next = document.getElementById("to-next");
next.addEventListener("click", function() { 
    clearTimeout(t);
    changeImage(false); 
    t = setTimeout( ()=>{ timer(); }, 1000*2);
});

点击切换按钮时,之前没有结束的定时器会被立即取消,并调用图片切换函数实现图片切换,图片切换后,再重新添加计时器让页面自动切换。

自由切换

自由切换是由点击小圆点实现的,因此我们也需要给小圆点添加事件监听器。将之前生成小圆点的代码稍微修改就可以了:

for(let i=0; i<images.length; i++) {
    let dot = document.createElement("span");   // 创建小圆点
    dot.className = "dot";  // 为创建的小圆点设置类名
    dot.id = "dot"+i;       // 为创建的小圆点设置id
    // 给小圆点添加监听事件
    dot.addEventListener("click", function() {
        // 先清除之前的定时器
        clearTimeout(t);
        dotID = this.getAttribute("id");    // 获取当前小圆点的id
        imgNow = Number(dotID.replace("dot", ""));  // 取出id里的数字
        document.getElementById("img-show").src = images[imgNow];   // 显示指定的图片
        // 将所有小圆点的样式设置成默认
        for(let i=0; i<dots.length; i++) {
            dots[i].className = "dot";
        }
        // 再将当前被选中的小圆点颜色变为灰色, 这里通过给它添加两个类实现
        this.className = "dot selected";
        // 设置定时器,两秒后再切换下一张
        t = setTimeout( ()=>{ timer(); }, 1000*2);
    });
    // 将创建的小圆点添加到小圆点容器中
    dotContainer.appendChild(dot);
}

在循环创建小圆点的同时,就给每个小圆点添加事件监听器,是不是很方便!

暂停自动切换

接下来实现当鼠标停留在图片上时,停止切换,鼠标挪开两秒后继续切换。这需要给图片添加事件监听器。

document.getElementById("img-show").addEventListener("mouseover", function() { 
    clearTimeout(t);    // 鼠标移入时取消定时器
});
document.getElementById("img-show").addEventListener("mouseout", function() { 
    t = setTimeout( ()=>{ timer(); }, 1000*2); // 鼠标移出时重新添加计时器
});

完成所有任务后,轮播图的效果就制作完成了!

JavaScript 源代码

const images = ['./image/1.png', './image/2.jpg', './image/3.jpg', './image/4.jpg', './image/5.jpg', './image/6.png'];
let imgNow = 0;
let t;
​
let dotContainer = document.getElementById("dot-container");
for(let i=0; i<images.length; i++) {
    let dot = document.createElement("span");
    dot.className = "dot";
    dot.id = "dot"+i; 
    dot.addEventListener("click", function() {
        clearTimeout(t);
        dotID = this.getAttribute("id");
        imgNow = Number(dotID.replace("dot", ""));
        document.getElementById("img-show").src = images[imgNow]; 
        for(let i=0; i<dots.length; i++) {
            dots[i].className = "dot";
        }
        this.className = "dot selected";
        t = setTimeout( ()=>{ timer(); }, 1000*2);
    });
    dotContainer.appendChild(dot);
}
let defaultDot = document.getElementById("dot0").className = "dot selected";
​
let dots = document.getElementsByClassName("dot");
​
t = setTimeout( ()=>{ 
    timer(); 
}, 1000*2);
​
document.getElementById("img-show").addEventListener("mouseover", function() { 
    clearTimeout(t);    
});
document.getElementById("img-show").addEventListener("mouseout", function() { 
    t = setTimeout( ()=>{ timer(); }, 1000*2); 
});
​
let previous = document.getElementById("to-pre");
previous.addEventListener("click", function() { 
    clearTimeout(t);
    changeImage(true);
    t = setTimeout( ()=>{ timer(); }, 1000*2); 
});
let next = document.getElementById("to-next");
next.addEventListener("click", function() { 
    clearTimeout(t);
    changeImage(false); 
    t = setTimeout( ()=>{ timer(); }, 1000*2);
});
​
function timer() {
    changeImage(false);
    t = setTimeout( ()=>{ timer(); }, 1000*2);
}
​
​
function changeImage(direction) {
    for(let i=0; i<dots.length; i++) {
        dots[i].className = "dot";
    }
    if(direction) {
        if(imgNow == 0) {
            imgNow = images.length-1;
        } else {
            imgNow -= 1;
        }
        document.getElementById("img-show").src = images[imgNow]; 
        dots[imgNow].className = "dot selected";
    } else {
        if(imgNow == images.length-1) {
            imgNow = 0;
        } else {
            imgNow += 1;
        }
        document.getElementById("img-show").src = images[imgNow];
        dots[imgNow].className = "dot selected";
    }
}

结语

轮播图的效果有很多种,做起来也挺有意思。本文所做的轮播图没有添加动画效果,适合不会做动画的初学者参考。如果对动画感兴趣,之后我也会分享添加了动画效果的轮播图。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐