一、原生 JS 定时切换(基础版)
实现思路:通过 setInterval 定时切换图片索引,结合按钮手动控制,利用 CSS opacity 实现显隐过渡。
HTML 结构
<div class="carousel-basic">
<div class="carousel-images">
<img src="image1.jpg" alt="Image 1" class="active">
<img src="image2.jpg" alt="Image 2">
<img src="image3.jpg" alt="Image 3">
</div>
<button class="prev-btn">上一张</button>
<button class="next-btn">下一张</button>
</div>
CSS 样式
.carousel-basic {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
margin: 0 auto;
}
.carousel-basic .carousel-images img {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.5s;
object-fit: cover;
}
.carousel-basic .carousel-images img.active {
opacity: 1;
}
.carousel-basic button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
.carousel-basic .prev-btn { left: 10px; }
.carousel-basic .next-btn { right: 10px; }
JavaScript
// 1. 获取DOM元素,定位轮播容器、图片、按钮
const carouselBasic = document.querySelector('.carousel-basic');
const images = carouselBasic.querySelectorAll('.carousel-images img');
const prevBtn = carouselBasic.querySelector('.prev-btn');
const nextBtn = carouselBasic.querySelector('.next-btn');
// 当前显示的图片索引,初始为0(第一张图)
let currentIndex = 0;
// 自动播放定时器,用于后续清除
let timer;
// 2. 核心方法:根据索引显示对应图片,隐藏其他图片
function showImage(index) {
// 遍历所有图片,移除active类(隐藏)
images.forEach(img => img.classList.remove('active'));
// 给目标索引的图片添加active类(显示)
images[index].classList.add('active');
}
// 3. 下一张图片:索引自增,取余实现循环(最后一张后回到第一张)
function nextImage() {
currentIndex = (currentIndex + 1) % images.length;
showImage(currentIndex);
}
// 4. 上一张图片:索引自减,加图片长度再取余,避免负索引
function prevImage() {
currentIndex = (currentIndex - 1 + images.length) % images.length;
showImage(currentIndex);
}
// 5. 自动播放:3秒切换一次图片
function startAutoPlay() {
timer = setInterval(nextImage, 3000);
}
// 6. 停止自动播放:清除定时器
function stopAutoPlay() {
clearInterval(timer);
}
// 7. 绑定上一张按钮点击事件:停止自动播放→切换图片→重新开启自动播放
prevBtn.addEventListener('click', () => {
stopAutoPlay();
prevImage();
startAutoPlay();
});
// 8. 绑定下一张按钮点击事件:逻辑同上
nextBtn.addEventListener('click', () => {
stopAutoPlay();
nextImage();
startAutoPlay();
});
// 9. 初始化:显示第一张图,开启自动播放
showImage(currentIndex);
startAutoPlay();
二、CSS3 Transition + JS 控制(流畅版)
实现思路:利用 CSS3 transition 属性实现平滑位移过渡,JS 控制 transform 改变图片轨道位置,比基础版动画更流畅。
HTML 结构
<div class="carousel-smooth">
<div class="carousel-track">
<img src="image1.jpg" alt="Image 1">
<img src="image2.jpg" alt="Image 2">
<img src="image3.jpg" alt="Image 3">
</div>
<button class="prev-btn">上一张</button>
<button class="next-btn">下一张</button>
</div>
CSS 样式
.carousel-smooth {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
margin: 0 auto;
}
.carousel-smooth .carousel-track {
display: flex;
width: 300%; /* 3张图总宽度,每张占100%容器宽度 */
height: 100%;
transition: transform 0.5s ease-in-out; /* 核心:平滑位移过渡 */
}
.carousel-smooth .carousel-track img {
width: 600px; /* 单张图宽度与容器一致 */
height: 100%;
object-fit: cover;
}
.carousel-smooth button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
.carousel-smooth .prev-btn { left: 10px; }
.carousel-smooth .next-btn { right: 10px; }
JavaScript
// 1. 获取DOM元素,定位轮播容器、图片轨道、图片、按钮
const carouselSmooth = document.querySelector('.carousel-smooth');
const track = carouselSmooth.querySelector('.carousel-track');
const imagesSmooth = carouselSmooth.querySelectorAll('.carousel-track img');
const prevBtnSmooth = carouselSmooth.querySelector('.prev-btn');
const nextBtnSmooth = carouselSmooth.querySelector('.next-btn');
// 当前显示的图片索引,初始为0
let currentIndexSmooth = 0;
// 容器宽度(与CSS一致,控制轨道位移距离)
const width = 600;
// 自动播放定时器
let timerSmooth;
// 2. 核心方法:更新轨道位置,通过transform实现位移
function updateTrack() {
// 位移距离 = 当前索引 × 容器宽度,负号表示向左位移
track.style.transform = `translateX(-${currentIndexSmooth * width}px)`;
}
// 3. 下一张图片:索引自增,取余循环
function nextImageSmooth() {
currentIndexSmooth = (currentIndexSmooth + 1) % imagesSmooth.length;
updateTrack(); // 触发轨道位移,CSS过渡生效
}
// 4. 上一张图片:索引自减,避免负索引
function prevImageSmooth() {
currentIndexSmooth = (currentIndexSmooth - 1 + imagesSmooth.length) % imagesSmooth.length;
updateTrack();
}
// 5. 自动播放:3秒切换一次
function startAutoPlaySmooth() {
timerSmooth = setInterval(nextImageSmooth, 3000);
}
// 6. 停止自动播放:清除定时器
function stopAutoPlaySmooth() {
clearInterval(timerSmooth);
}
// 7. 绑定上一张按钮事件:停止自动播放→切换→重启
prevBtnSmooth.addEventListener('click', () => {
stopAutoPlaySmooth();
prevImageSmooth();
startAutoPlaySmooth();
});
// 8. 绑定下一张按钮事件:逻辑同上
nextBtnSmooth.addEventListener('click', () => {
stopAutoPlaySmooth();
nextImageSmooth();
startAutoPlaySmooth();
});
// 9. 初始化:开启自动播放
startAutoPlaySmooth();
三、面向对象封装(可复用版)
实现思路:将轮播图功能封装为 Carousel 类,支持配置参数(自动播放、间隔时间、宽度等),可实例化多个轮播图,复用性强。
HTML 结构
<div class="carousel-oop" id="carousel1">
<div class="carousel-track">
<img src="image1.jpg" alt="Image 1">
<img src="image2.jpg" alt="Image 2">
<img src="image3.jpg" alt="Image 3">
</div>
<button class="prev-btn">上一张</button>
<button class="next-btn">下一张</button>
</div>
CSS 样式
.carousel-oop {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
margin: 0 auto;
}
.carousel-oop .carousel-track {
display: flex;
height: 100%;
transition: transform 0.5s ease-in-out;
}
.carousel-oop .carousel-track img {
width: 600px;
height: 100%;
object-fit: cover;
}
.carousel-oop button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
.carousel-oop .prev-btn { left: 10px; }
.carousel-oop .next-btn { right: 10px; }
JavaScript
// 1. 封装Carousel类,统一管理轮播逻辑,支持自定义配置
class Carousel {
// 构造函数:接收轮播容器元素和配置参数(默认空对象)
constructor(element, options = {}) {
// 绑定DOM元素
this.container = element;
this.track = this.container.querySelector('.carousel-track');
this.images = this.container.querySelectorAll('.carousel-track img');
this.prevBtn = this.container.querySelector('.prev-btn');
this.nextBtn = this.container.querySelector('.next-btn');
// 2. 合并默认配置与用户配置,用户配置优先级更高
this.options = {
autoPlay: true, // 默认自动播放
interval: 3000, // 默认切换间隔3秒
width: 600, // 默认容器宽度600px
...options
};
// 初始化状态
this.currentIndex = 0; // 当前图片索引
this.timer = null; // 自动播放定时器
// 3. 初始化执行(轨道宽度、事件绑定)
this.init();
}
// 4. 初始化方法:完成轨道宽度设置、事件绑定
init() {
// 初始化轨道总宽度 = 图片数量 × 容器宽度
this.track.style.width = `${this.images.length * this.options.width}px`;
this.bindEvents(); // 绑定按钮、鼠标悬停事件
// 若开启自动播放,初始化时启动
if (this.options.autoPlay) this.startAutoPlay();
}
// 5. 核心方法:更新轨道位置,控制图片切换
update() {
this.track.style.transform = `translateX(-${this.currentIndex * this.options.width}px)`;
}
// 6. 下一张图片:索引循环自增
next() {
this.currentIndex = (this.currentIndex + 1) % this.images.length;
this.update();
}
// 7. 上一张图片:索引循环自减
prev() {
this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
this.update();
}
// 8. 开启自动播放:按配置间隔执行next方法
startAutoPlay() {
this.timer = setInterval(() => this.next(), this.options.interval);
}
// 9. 停止自动播放:清除定时器
stopAutoPlay() {
clearInterval(this.timer);
}
// 10. 事件绑定:统一管理所有交互事件
bindEvents() {
// 上一张按钮点击事件
this.prevBtn.addEventListener('click', () => {
this.stopAutoPlay();
this.prev();
if (this.options.autoPlay) this.startAutoPlay();
});
// 下一张按钮点击事件
this.nextBtn.addEventListener('click', () => {
this.stopAutoPlay();
this.next();
if (this.options.autoPlay) this.startAutoPlay();
});
// 鼠标悬停暂停,离开继续播放(优化体验)
this.container.addEventListener('mouseenter', () => this.stopAutoPlay());
this.container.addEventListener('mouseleave', () => {
if (this.options.autoPlay) this.startAutoPlay();
});
}
}
// 11. 实例化轮播图:传入容器元素和自定义配置
const carousel1 = new Carousel(document.getElementById('carousel1'), {
autoPlay: true,
interval: 3000,
width: 600
});
// 可实例化第二个轮播图(需新增对应HTML结构)
// const carousel2 = new Carousel(document.getElementById('carousel2'), { ... });
四、无缝滚动轮播图(进阶版)
实现思路:核心是「复制第一张图追加到轨道末尾」,当轮播到复制的图片时,瞬间将轨道复位到初始位置(无过渡),实现视觉上的无缝循环。结合 CSS3 transition 平滑过渡,JS 控制索引切换与复位逻辑,支持自动播放、手动控制。
HTML 结构
<div class="carousel-seamless">
<div class="carousel-track">
<img src="image1.jpg" alt="Image 1">
<img src="image2.jpg" alt="Image 2">
<img src="image3.jpg" alt="Image 3">
<!-- 复制第一张图,用于无缝衔接 -->
</div>
<button class="prev-btn">上一张</button>
<button class="next-btn">下一张</button>
</div>
CSS 样式
.carousel-seamless {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
margin: 0 auto;
}
.carousel-seamless .carousel-track {
display: flex;
height: 100%;
transition: transform 0.5s ease-in-out; /* 平滑过渡 */
}
.carousel-seamless .carousel-track img {
width: 600px; /* 与容器宽度一致 */
height: 100%;
object-fit: cover;
flex-shrink: 0; /* 禁止图片收缩,保证宽度一致,关键! */
}
.carousel-seamless button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
z-index: 10; /* 按钮置于顶层,避免被遮挡 */
}
.carousel-seamless .prev-btn { left: 10px; }
.carousel-seamless .next-btn { right: 10px; }
JavaScript
// 1. 获取DOM元素,定位轮播容器、轨道、图片、按钮
const carouselSeamless = document.querySelector('.carousel-seamless');
const track = carouselSeamless.querySelector('.carousel-track');
const images = carouselSeamless.querySelectorAll('.carousel-track img');
const prevBtn = carouselSeamless.querySelector('.prev-btn');
const nextBtn = carouselSeamless.querySelector('.next-btn');
// 容器宽度(与CSS一致)
const width = 600;
// 当前图片索引,初始为0
let currentIndex = 0;
// 自动播放定时器
let timer;
// 2. 无缝滚动核心步骤1:复制第一张图,追加到轨道末尾(视觉衔接关键)
const firstImg = images[0].cloneNode(true); // 克隆第一张图,true表示复制子节点
track.appendChild(firstImg); // 追加到轨道末尾
// 更新图片集合(包含克隆的第一张图,共4张)
const allImages = carouselSeamless.querySelectorAll('.carousel-track img');
// 更新轨道总宽度 = 所有图片(原3张+克隆1张)× 容器宽度
track.style.width = `${allImages.length * width}px`;
// 3. 核心方法:更新轨道位置,控制位移
function updateTrack() {
track.style.transform = `translateX(-${currentIndex * width}px)`;
}
// 4. 下一张图片(无缝核心逻辑)
function nextImage() {
currentIndex++;
updateTrack(); // 触发平滑过渡,向左位移
// 关键判断:当轮播到克隆的第一张图(索引=原图片长度3)时
if (currentIndex === images.length) {
// 等待过渡完成(与CSS transition时间一致,500ms)
setTimeout(() => {
track.style.transition = 'none'; // 取消过渡,实现瞬间复位
currentIndex = 0; // 索引重置为0(真正的第一张图)
updateTrack(); // 瞬间移动到初始位置,无视觉卡顿
// 重置过渡效果,保证下次切换正常平滑
setTimeout(() => {
track.style.transition = 'transform 0.5s ease-in-out';
}, 10); // 延迟10ms,避免过渡冲突
}, 500);
}
}
// 5. 上一张图片(无缝核心逻辑)
function prevImage() {
// 关键判断:当前是第一张图(索引=0)时
if (currentIndex === 0) {
track.style.transition = 'none'; // 取消过渡
currentIndex = images.length; // 索引设为克隆图的位置(3)
updateTrack(); // 瞬间移动到克隆图位置
// 延迟10ms,重新开启过渡,再切换到上一张(原最后一张图)
setTimeout(() => {
track.style.transition = 'transform 0.5s ease-in-out';
currentIndex--;
updateTrack();
}, 10);
} else {
// 非第一张图,正常索引自减,平滑过渡
currentIndex--;
updateTrack();
}
}
// 6. 自动播放:3秒切换一次
function startAutoPlay() {
timer = setInterval(nextImage, 3000);
}
// 7. 停止自动播放:清除定时器
function stopAutoPlay() {
clearInterval(timer);
}
// 8. 绑定上一张按钮事件:停止→切换→重启
prevBtn.addEventListener('click', () => {
stopAutoPlay();
prevImage();
startAutoPlay();
});
// 9. 绑定下一张按钮事件:逻辑同上
nextBtn.addEventListener('click', () => {
stopAutoPlay();
nextImage();
startAutoPlay();
});
// 10. 鼠标悬停暂停,离开继续(优化体验)
carouselSeamless.addEventListener('mouseenter', stopAutoPlay);
carouselSeamless.addEventListener('mouseleave', startAutoPlay);
// 11. 初始化:开启自动播放
startAutoPlay();
五、requestAnimationFrame 优化版
实现思路:用 requestAnimationFrame 替代 setInterval,避免定时器卡顿问题,结合时间戳控制切换间隔,动画更流畅、性能更优,适合高刷新率设备和复杂场景。
HTML 结构
<div class="carousel-request">
<div class="carousel-track">
<img src="image1.jpg" alt="Image 1">
<img src="image2.jpg" alt="Image 2">
<img src="image3.jpg" alt="Image 3">
</div>
<button class="prev-btn">上一张</button>
<button class="next-btn">下一张</button>
</div>
CSS 样式
.carousel-request {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
margin: 0 auto;
}
.carousel-request .carousel-track {
display: flex;
height: 100%;
transition: transform 0.5s ease-in-out;
}
.carousel-request .carousel-track img {
width: 600px;
height: 100%;
object-fit: cover;
flex-shrink: 0;
}
.carousel-request button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
z-index: 10;
}
.carousel-request .prev-btn { left: 10px; }
.carousel-request .next-btn { right: 10px; }
JavaScript
// 1. 获取DOM元素,定位容器、轨道、图片、按钮
const carouselRequest = document.querySelector('.carousel-request');
const track = carouselRequest.querySelector('.carousel-track');
const images = carouselRequest.querySelectorAll('.carousel-track img');
const prevBtn = carouselRequest.querySelector('.prev-btn');
const nextBtn = carouselRequest.querySelector('.next-btn');
// 容器宽度
const width = 600;
// 当前图片索引
let currentIndex = 0;
// 自动播放相关:时间戳(控制间隔)、请求动画ID(用于取消)
let lastTime = 0;
const interval = 3000; // 切换间隔3秒
let requestId = null;
// 2. 核心方法:更新轨道位置
function updateTrack() {
track.style.transform = `translateX(-${currentIndex * width}px)`;
}
// 3. 下一张图片:索引循环自增
function nextImage() {
currentIndex = (currentIndex + 1) % images.length;
updateTrack();
}
// 4. 上一张图片:索引循环自减
function prevImage() {
currentIndex = (currentIndex - 1 + images.length) % images.length;
updateTrack();
}
// 5. 自动播放核心:requestAnimationFrame 帧动画
function autoPlay(timestamp) {
// 时间戳判断:当前时间 - 上一次切换时间 ≥ 间隔时间,才执行切换
if (!lastTime || timestamp - lastTime >= interval) {
nextImage(); // 切换图片
lastTime = timestamp; // 更新上一次切换时间戳
}
// 递归调用,实现持续帧动画(浏览器自动优化帧率)
requestId = requestAnimationFrame(autoPlay);
}
// 6. 开启自动播放:启动帧动画
function startAutoPlay() {
// 先取消已有动画,避免重复启动
if (requestId) cancelAnimationFrame(requestId);
requestId = requestAnimationFrame(autoPlay);
}
// 7. 停止自动播放:取消帧动画
function stopAutoPlay() {
if (requestId) cancelAnimationFrame(requestId);
requestId = null; // 重置请求ID
}
// 8. 绑定上一张按钮事件:停止→切换→重启
prevBtn.addEventListener('click', () => {
stopAutoPlay();
prevImage();
startAutoPlay();
});
// 9. 绑定下一张按钮事件:逻辑同上
nextBtn.addEventListener('click', () => {
stopAutoPlay();
nextImage();
startAutoPlay();
});
// 10. 鼠标悬停暂停,离开继续
carouselRequest.addEventListener('mouseenter', stopAutoPlay);
carouselRequest.addEventListener('mouseleave', startAutoPlay);
// 11. 初始化:开启高性能自动播放
startAutoPlay();