1. 最终效果预览
  2. 准备工作
  3. 第一步:基础 HTML 结构
  4. 第二步:CSS 样式美化
  5. 第三步:JavaScript 核心逻辑实现
    • 自动播放
    • 指示器点击切换
    • 左右箭头切换
    • 无缝循环效果
  6. 第四步:整合与优化
  7. 完整代码
  8. 进阶与扩展

最终效果预览

在开始之前,我们先看看我们要制作的东西是什么样的,它应该包含:

javascript图片轮播教程
(图片来源网络,侵删)
  • 一系列可以自动切换的图片。
  • 底部有圆点指示器,显示当前是第几张图片,并可以点击切换。
  • 左右两侧有箭头,可以手动切换到上一张或下一张。
  • 切换时有平滑的过渡动画。

准备工作

你需要准备以下三样东西:

  1. HTML 文件: 创建一个 index.html 文件。
  2. CSS 文件: 创建一个 style.css 文件。
  3. JavaScript 文件: 创建一个 script.js 文件。
  4. 图片: 准备几张你想要轮播的图片,并放在一个名为 images 的文件夹里,为了演示,你可以使用 unsplash.com 上的随机图片。

第一步:基础 HTML 结构

我们用 HTML 搭建轮播图的“骨架”,打开 index.html 文件,输入以下代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">JavaScript 图片轮播</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="carousel-container">
        <!-- 图片容器 -->
        <div class="carousel-slides">
            <!-- 使用 data-index 来追踪图片的索引 -->
            <div class="carousel-slide active" data-index="0">
                <img src="images/slide1.jpg" alt="Slide 1">
            </div>
            <div class="carousel-slide" data-index="1">
                <img src="images/slide2.jpg" alt="Slide 2">
            </div>
            <div class="carousel-slide" data-index="2">
                <img src="images/slide3.jpg" alt="Slide 3">
            </div>
            <div class="carousel-slide" data-index="3">
                <img src="images/slide4.jpg" alt="Slide 4">
            </div>
        </div>
        <!-- 左右箭头 -->
        <button class="carousel-btn prev-btn">&#10094;</button>
        <button class="carousel-btn next-btn">&#10095;</button>
        <!-- 指示器 -->
        <div class="carousel-indicators">
            <span class="indicator active" data-index="0"></span>
            <span class="indicator" data-index="1"></span>
            <span class="indicator" data-index="2"></span>
            <span class="indicator" data-index="3"></span>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

代码解释:

  • .carousel-container: 最外层的容器,用于包裹整个轮播组件。
  • .carousel-slides: 包含所有图片的容器。
  • .carousel-slide: 单张图片的容器,我们给第一张图片添加了 active 类,表示它是当前显示的图片。data-index 属性用于标记图片的顺序(从0开始)。
  • .carousel-btn: 左右箭头按钮。
  • .carousel-indicators: 指示器(小圆点)的容器。
  • .indicator: 单个小圆点,同样,第一个小圆点有 active 类,并且也有 data-index 属性。

第二步:CSS 样式美化

我们来添加 CSS 样式,让轮播图看起来像模像样,打开 style.css 文件,输入以下代码:

javascript图片轮播教程
(图片来源网络,侵删)
/* 基础重置和样式 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: #f4f4f4;
}
/* 轮播图容器 */
.carousel-container {
    position: relative;
    width: 800px;
    max-width: 100%; /* 响应式 */
    overflow: hidden; /* 隐藏溢出的图片 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
/* 图片容器 - 这是实现切换效果的关键 */
.carousel-slides {
    display: flex; /* 使用 Flexbox 布局 */
    transition: transform 0.5s ease-in-out; /* 添加平滑过渡效果 */
}
/* 单张图片 */
.carousel-slide {
    min-width: 100%; /* 每张图片占据容器的100%宽度 */
    height: 400px;
}
.carousel-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover; /* 保证图片填充且不变形 */
}
/* 左右箭头 */
.carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background-color: rgba(0, 0, 0, 0.5);
    color: white;
    border: none;
    font-size: 24px;
    padding: 10px 15px;
    cursor: pointer;
    border-radius: 50%;
    transition: background-color 0.3s ease;
}
.carousel-btn:hover {
    background-color: rgba(0, 0, 0, 0.8);
}
.prev-btn {
    left: 10px;
}
.next-btn {
    right: 10px;
}
/* 指示器 */
.carousel-indicators {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 10px;
}
.indicator {
    width: 12px;
    height: 12px;
    background-color: rgba(255, 255, 255, 0.5);
    border-radius: 50%;
    cursor: pointer;
    transition: background-color 0.3s ease;
}
.indicator.active {
    background-color: white;
}

代码解释:

  • .carousel-container 设置了 overflow: hidden,这样当图片移动时,超出容器的部分就会被隐藏。
  • .carousel-slides 使用 display: flex 让所有图片排成一行。transition: transform 是核心,它会让 transform 属性的变化(如平移)产生平滑的动画。
  • .carousel-slide 设置 min-width: 100% 确保每张图片都占据一行。
  • .carousel-btn 使用 position: absolute 将按钮定位在图片的两侧。
  • .indicator 定义了小圆点的样式,.active 类用于高亮当前指示器。

第三步:JavaScript 核心逻辑

这是最关键的一步,我们将用 JavaScript 来控制轮播图的行为,打开 script.js 文件,让我们一步步实现功能。

1 获取 DOM 元素和初始化变量

我们需要获取 HTML 中我们需要的元素,并定义一些变量来管理轮播状态。

document.addEventListener('DOMContentLoaded', () => {
    // 1. 获取所有需要的 DOM 元素
    const slides = document.querySelectorAll('.carousel-slide');
    const indicators = document.querySelectorAll('.indicator');
    const prevBtn = document.querySelector('.prev-btn');
    const nextBtn = document.querySelector('.next-btn');
    const slidesContainer = document.querySelector('.carousel-slides');
    // 2. 初始化变量
    let currentIndex = 0; // 当前显示的图片索引
    const totalSlides = slides.length; // 图片总数
    let slideInterval; // 用于存储定时器的变量
    const intervalTime = 3000; // 自动切换的时间间隔(毫秒)
    // ... 接下来我们将在这里添加其他函数 ...
});

2 核心函数:goToSlide(index)

这个函数是轮播图的“大脑”,它负责将轮播图切换到指定的索引位置。

javascript图片轮播教程
(图片来源网络,侵删)
// 在 script.js 中添加这个函数
function goToSlide(index) {
    // 检查索引是否越界
    if (index < 0) {
        index = totalSlides - 1; // 如果是负数,跳转到最后一张
    } else if (index >= totalSlides) {
        index = 0; // 如果超出总数,跳转到第一张
    }
    // 更新当前索引
    currentIndex = index;
    // 移动图片容器
    // transform: translateX(-${currentIndex * 100}%)
    // 意思是:向左移动 当前索引 * 100% 的宽度
    slidesContainer.style.transform = `translateX(-${currentIndex * 100}%)`;
    // 更新指示器状态
    indicators.forEach(indicator => {
        indicator.classList.remove('active');
    });
    indicators[currentIndex].classList.add('active');
}

3 自动播放功能

使用 setInterval 来实现每隔一段时间自动切换到下一张图片。

// 在 script.js 中添加这个函数
function startSlideShow() {
    // 清除之前的定时器,防止重复设置
    clearInterval(slideInterval);
    // 设置新的定时器
    slideInterval = setInterval(() => {
        goToSlide(currentIndex + 1);
    }, intervalTime);
}

4 事件监听器

我们需要将用户的操作(点击箭头、点击指示器)与我们的函数连接起来。

// 在 script.js 的 DOMContentLoaded 事件处理函数内部添加
// 左右箭头点击事件
prevBtn.addEventListener('click', () => {
    goToSlide(currentIndex - 1);
    startSlideShow(); // 用户操作后重置定时器
});
nextBtn.addEventListener('click', () => {
    goToSlide(currentIndex + 1);
    startSlideShow(); // 用户操作后重置定时器
});
// 指示器点击事件
indicators.forEach(indicator => {
    indicator.addEventListener('click', () => {
        const index = parseInt(indicator.getAttribute('data-index'));
        goToSlide(index);
        startSlideShow(); // 用户操作后重置定时器
    });
});
// 鼠标悬停时暂停自动播放
const carouselContainer = document.querySelector('.carousel-container');
carouselContainer.addEventListener('mouseenter', () => {
    clearInterval(slideInterval);
});
// 鼠标离开时恢复自动播放
carouselContainer.addEventListener('mouseleave', () => {
    startSlideShow();
});
// 页面加载完成后,启动自动播放
startSlideShow();

事件监听器解释:

  • 箭头点击: 点击时调用 goToSlide 并传入 currentIndex + 1currentIndex - 1
  • 指示器点击: 获取被点击的指示器上的 data-index 值,然后调用 goToSlide
  • 重置定时器: 每次用户手动操作后,我们调用 startSlideShow(),这会先清除旧的定时器,再设置一个新的,这样做的目的是,用户操作后,轮播图会重新计时,而不是在用户操作后马上又切换。
  • 鼠标悬停/离开: 提升用户体验,当鼠标悬停在轮播图上时,暂停自动播放;鼠标离开后,恢复播放。

第四步:整合与优化

将上面所有 JavaScript 代码块整合到 script.js 文件中,并确保它们的顺序正确,完整的 script.js 代码将在下一节给出。

至此,一个功能完整的图片轮播图就已经完成了!


完整代码

为了方便你直接复制使用,这里是三个文件的完整代码。

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">JavaScript 图片轮播</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="carousel-container">
        <div class="carousel-slides">
            <div class="carousel-slide active" data-index="0">
                <img src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80" alt="Slide 1">
            </div>
            <div class="carousel-slide" data-index="1">
                <img src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80" alt="Slide 2">
            </div>
            <div class="carousel-slide" data-index="2">
                <img src="https://images.unsplash.com/photo-1518837695005-2083093ee35b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80" alt="Slide 3">
            </div>
            <div class="carousel-slide" data-index="3">
                <img src="https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80" alt="Slide 4">
            </div>
        </div>
        <button class="carousel-btn prev-btn">&#10094;</button>
        <button class="carousel-btn next-btn">&#10095;</button>
        <div class="carousel-indicators">
            <span class="indicator active" data-index="0"></span>
            <span class="indicator" data-index="1"></span>
            <span class="indicator" data-index="2"></span>
            <span class="indicator" data-index="3"></span>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

style.css

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: #f4f4f4;
}
.carousel-container {
    position: relative;
    width: 800px;
    max-width: 100%;
    overflow: hidden;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.carousel-slides {
    display: flex;
    transition: transform 0.5s ease-in-out;
}
.carousel-slide {
    min-width: 100%;
    height: 400px;
}
.carousel-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background-color: rgba(0, 0, 0, 0.5);
    color: white;
    border: none;
    font-size: 24px;
    padding: 10px 15px;
    cursor: pointer;
    border-radius: 50%;
    transition: background-color 0.3s ease;
}
.carousel-btn:hover {
    background-color: rgba(0, 0, 0, 0.8);
}
.prev-btn {
    left: 10px;
}
.next-btn {
    right: 10px;
}
.carousel-indicators {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 10px;
}
.indicator {
    width: 12px;
    height: 12px;
    background-color: rgba(255, 255, 255, 0.5);
    border-radius: 50%;
    cursor: pointer;
    transition: background-color 0.3s ease;
}
.indicator.active {
    background-color: white;
}

script.js

document.addEventListener('DOMContentLoaded', () => {
    // 1. 获取所有需要的 DOM 元素
    const slides = document.querySelectorAll('.carousel-slide');
    const indicators = document.querySelectorAll('.indicator');
    const prevBtn = document.querySelector('.prev-btn');
    const nextBtn = document.querySelector('.next-btn');
    const slidesContainer = document.querySelector('.carousel-slides');
    // 2. 初始化变量
    let currentIndex = 0;
    const totalSlides = slides.length;
    let slideInterval;
    const intervalTime = 3000;
    // 核心函数:切换到指定索引的幻灯片
    function goToSlide(index) {
        if (index < 0) {
            index = totalSlides - 1;
        } else if (index >= totalSlides) {
            index = 0;
        }
        currentIndex = index;
        slidesContainer.style.transform = `translateX(-${currentIndex * 100}%)`;
        indicators.forEach(indicator => {
            indicator.classList.remove('active');
        });
        indicators[currentIndex].classList.add('active');
    }
    // 自动播放函数
    function startSlideShow() {
        clearInterval(slideInterval);
        slideInterval = setInterval(() => {
            goToSlide(currentIndex + 1);
        }, intervalTime);
    }
    // 3. 添加事件监听器
    prevBtn.addEventListener('click', () => {
        goToSlide(currentIndex - 1);
        startSlideShow();
    });
    nextBtn.addEventListener('click', () => {
        goToSlide(currentIndex + 1);
        startSlideShow();
    });
    indicators.forEach(indicator => {
        indicator.addEventListener('click', () => {
            const index = parseInt(indicator.getAttribute('data-index'));
            goToSlide(index);
            startSlideShow();
        });
    });
    // 鼠标悬停暂停,离开恢复
    const carouselContainer = document.querySelector('.carousel-container');
    carouselContainer.addEventListener('mouseenter', () => {
        clearInterval(slideInterval);
    });
    carouselContainer.addEventListener('mouseleave', () => {
        startSlideShow();
    });
    // 4. 启动轮播
    startSlideShow();
});

进阶与扩展

当你掌握了基础版本后,可以尝试以下扩展功能来提升你的技能:

  1. 触摸滑动支持: 使用 touchstart, touchmove, 和 touchend 事件,让轮播图在手机上可以通过手指滑动来切换。
  2. 淡入淡出效果: 修改 CSS 和 JavaScript,使用 opacityz-index 来实现图片淡入淡出的切换效果,而不是左右滑动。
  3. 动态加载图片: 修改 JavaScript,使其从一个数组或 API 动态获取图片 URL,而不是在 HTML 中硬编码,这样轮播图的内容就可以更灵活地更改。
  4. 使用 CSS 动画: 将 transition 替换为更复杂的 @keyframes 动画,可以实现更酷炫的切换效果。
  5. 封装成插件/类: 将所有轮播图的逻辑封装到一个 JavaScript 类中,这样你就可以轻松地在页面的不同地方创建多个独立的轮播图实例,而不会互相干扰。

希望这份详细的教程能帮助你成功构建出你的第一个 JavaScript 图片轮播图!祝你编码愉快!