文章目录
carousel.html
html
<!DOCTYPE html> <!-- 声明文档类型为HTML5 -->
<html lang="zh-CN"> <!-- 开始HTML文档,设置语言为中文 -->
<head> <!-- 头部区域,包含元数据和资源引用 -->
<meta charset="UTF-8"> <!-- 设置字符编码为UTF-8,支持中文等多语言 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 设置视口,使页面在移动设备上正确缩放 -->
<title>响应式轮播图</title> <!-- 设置页面标题,显示在浏览器标签上 -->
<link rel="stylesheet" href="carousel.css"> <!-- 引入外部CSS样式表 -->
</head>
<body> <!-- 网页主体内容区域 -->
<div class="carousel-container"> <!-- 轮播图外层容器,控制整体宽度和居中 -->
<div class="carousel-wrapper"> <!-- 轮播图包装器,设置相对定位和溢出隐藏 -->
<div class="carousel-slides"> <!-- 轮播图幻灯片区域,包含所有轮播图片 -->
<div class="carousel-slide active"> <!-- 第一张幻灯片,设置为激活状态(默认显示) -->
<img src="https://picsum.photos/800/400?random=1" alt="幻灯片1"> <!-- 图片元素,使用随机图片服务,alt属性提供替代文本 -->
</div>
<div class="carousel-slide"> <!-- 第二张幻灯片,初始状态为隐藏 -->
<img src="https://picsum.photos/800/400?random=2" alt="幻灯片2"> <!-- 第二张随机图片 -->
</div>
<div class="carousel-slide"> <!-- 第三张幻灯片,初始状态为隐藏 -->
<img src="https://picsum.photos/800/400?random=3" alt="幻灯片3"> <!-- 第三张随机图片 -->
</div>
<div class="carousel-slide"> <!-- 第四张幻灯片,初始状态为隐藏 -->
<img src="https://picsum.photos/800/400?random=4" alt="幻灯片4"> <!-- 第四张随机图片 -->
</div>
</div>
<!-- 导航按钮 --> <!-- 注释说明下面是导航按钮区域 -->
<button class="carousel-button prev"><</button> <!-- 上一张按钮,使用<显示<符号 -->
<button class="carousel-button next">></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>
</div>
<script src="carousel.js"></script> <!-- 引入外部JavaScript文件,处理轮播图交互逻辑 -->
</body>
</html> <!-- 结束HTML文档 -->
carousel.css
css
* { /* 通用选择器,应用于页面中的所有元素 */
margin: 0; /* 移除所有元素的外边距 */
padding: 0; /* 移除所有元素的内边距 */
box-sizing: border-box; /* 将盒模型设置为border-box,使元素的宽高包含padding和border */
}
body { /* 应用于网页的body元素 */
font-family: 'Arial', sans-serif; /* 设置字体为Arial,如果不可用则使用系统默认无衬线字体 */
display: flex; /* 使用弹性布局 */
justify-content: center; /* 水平居中对齐 */
align-items: center; /* 垂直居中对齐 */
min-height: 100vh; /* 最小高度为视口高度的100% */
background-color: #f5f5f5; /* 设置浅灰色背景 */
}
.carousel-container { /* 轮播图最外层容器 */
width: 100%; /* 宽度为父元素的100% */
max-width: 800px; /* 最大宽度为800px,防止在大屏幕上过宽 */
margin: 0 auto; /* 上下边距为0,左右自动(居中) */
}
.carousel-wrapper { /* 轮播图包装器 */
position: relative; /* 设置相对定位,作为内部绝对定位元素的参考 */
overflow: hidden; /* 隐藏超出容器的内容 */
border-radius: 10px; /* 设置圆角为10px */
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); /* 添加阴影效果,营造立体感 */
}
.carousel-slides { /* 包含所有幻灯片的容器 */
display: flex; /* 使用弹性布局,使幻灯片水平排列 */
transition: transform 0.5s ease; /* 添加过渡效果,使移动平滑 */
}
.carousel-slide { /* 单个幻灯片样式 */
min-width: 100%; /* 最小宽度为父容器的100%,确保幻灯片占满整个容器 */
opacity: 0; /* 初始透明度为0(隐藏状态) */
transition: opacity 0.5s ease; /* 添加透明度过渡效果,使切换平滑 */
position: absolute; /* 绝对定位,使幻灯片可以叠放 */
top: 0; /* 距顶部0px */
left: 0; /* 距左侧0px */
}
.carousel-slide.active { /* 当前显示的激活幻灯片 */
opacity: 1; /* 透明度为1(完全显示) */
position: relative; /* 改为相对定位,使其占据空间,撑开容器 */
}
.carousel-slide img { /* 幻灯片中的图片 */
width: 100%; /* 宽度为父元素的100% */
height: auto; /* 高度自动,保持图片原始比例 */
display: block; /* 设置为块级元素,避免底部间隙 */
}
.carousel-button { /* 导航按钮的基本样式 */
position: absolute; /* 绝对定位,相对于.carousel-wrapper */
top: 50%; /* 从顶部偏移50% */
transform: translateY(-50%); /* 向上平移自身高度的50%,实现垂直居中 */
width: 40px; /* 宽度为40px */
height: 40px; /* 高度为40px */
border-radius: 50%; /* 设置为圆形 */
background-color: rgba(255, 255, 255, 0.7); /* 半透明白色背景 */
border: none; /* 移除边框 */
cursor: pointer; /* 鼠标悬停时显示手型光标 */
font-size: 20px; /* 字体大小为20px */
font-weight: bold; /* 字体加粗 */
color: #333; /* 文字颜色为深灰色 */
display: flex; /* 使用弹性布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
transition: all 0.3s ease; /* 添加过渡效果 */
z-index: 10; /* 设置层级,确保按钮显示在幻灯片上方 */
}
.carousel-button:hover { /* 鼠标悬停在按钮上时的样式 */
background-color: rgba(255, 255, 255, 0.9); /* 增加背景不透明度 */
}
.carousel-button.prev { /* 上一张按钮的位置 */
left: 10px; /* 距左侧10px */
}
.carousel-button.next { /* 下一张按钮的位置 */
right: 10px; /* 距右侧10px */
}
.carousel-indicators { /* 指示器点容器 */
position: absolute; /* 绝对定位 */
bottom: 15px; /* 距底部15px */
left: 50%; /* 距左侧50% */
transform: translateX(-50%); /* 向左平移自身宽度的50%,实现水平居中 */
display: flex; /* 使用弹性布局,使指示器点水平排列 */
gap: 10px; /* 指示器点之间的间距为10px */
z-index: 10; /* 设置层级,确保指示器显示在幻灯片上方 */
}
.indicator { /* 单个指示器点的样式 */
width: 12px; /* 宽度为12px */
height: 12px; /* 高度为12px */
border-radius: 50%; /* 设置为圆形 */
background-color: rgba(255, 255, 255, 0.5); /* 半透明白色背景 */
cursor: pointer; /* 鼠标悬停时显示手型光标 */
transition: all 0.3s ease; /* 添加过渡效果 */
}
.indicator.active { /* 当前激活的指示器点 */
background-color: white; /* 背景色为纯白色 */
transform: scale(1.2); /* 放大到原来的1.2倍 */
}
/* 响应式设计 */ /* 针对不同屏幕尺寸的样式调整 */
@media (max-width: 768px) { /* 当屏幕宽度小于等于768px时应用以下样式 */
.carousel-button { /* 在小屏幕上调整按钮大小 */
width: 30px; /* 减小宽度为30px */
height: 30px; /* 减小高度为30px */
font-size: 16px; /* 减小字体大小为16px */
}
.indicator { /* 在小屏幕上调整指示器点大小 */
width: 10px; /* 减小宽度为10px */
height: 10px; /* 减小高度为10px */
}
}
carousel.js
javascript
document.addEventListener('DOMContentLoaded', function () { // 当DOM内容加载完成后执行函数
// 获取所有必要的元素
const slides = document.querySelectorAll('.carousel-slide'); // 获取所有幻灯片元素
const indicators = document.querySelectorAll('.indicator'); // 获取所有指示器点
const prevButton = document.querySelector('.carousel-button.prev'); // 获取上一张按钮
const nextButton = document.querySelector('.carousel-button.next'); // 获取下一张按钮
let currentIndex = 0; // 当前显示的幻灯片索引,初始为0(第一张)
let interval; // 存储自动轮播定时器的变量
const autoPlayDelay = 5000; // 自动轮播间隔时间,设置为5000毫秒(5秒)
// 初始化自动轮播
startAutoPlay(); // 页面加载后立即开始自动轮播
// 设置当前激活的幻灯片
function setActiveSlide(index) { // 定义切换幻灯片的函数,接收目标索引参数
// 移除所有激活状态
slides.forEach(slide => slide.classList.remove('active')); // 移除所有幻灯片的active类
indicators.forEach(indicator => indicator.classList.remove('active')); // 移除所有指示器点的active类
// 设置新的激活状态
slides[index].classList.add('active'); // 为目标幻灯片添加active类
indicators[index].classList.add('active'); // 为对应的指示器点添加active类
currentIndex = index; // 更新当前索引变量
}
// 前进到下一张幻灯片
function nextSlide() { // 定义切换到下一张幻灯片的函数
let newIndex = currentIndex + 1; // 计算下一张幻灯片的索引
if (newIndex >= slides.length) { // 如果索引超出范围
newIndex = 0; // 循环回到第一张
}
setActiveSlide(newIndex); // 调用setActiveSlide函数切换到新索引的幻灯片
}
// 后退到上一张幻灯片
function prevSlide() { // 定义切换到上一张幻灯片的函数
let newIndex = currentIndex - 1; // 计算上一张幻灯片的索引
if (newIndex < 0) { // 如果索引小于0
newIndex = slides.length - 1; // 循环到最后一张
}
setActiveSlide(newIndex); // 调用setActiveSlide函数切换到新索引的幻灯片
}
// 开始自动轮播
function startAutoPlay() { // 定义开始自动轮播的函数
stopAutoPlay(); // 先停止可能存在的定时器,避免多个定时器同时运行
interval = setInterval(nextSlide, autoPlayDelay); // 设置定时器,每隔autoPlayDelay毫秒自动调用nextSlide函数
}
// 停止自动轮播
function stopAutoPlay() { // 定义停止自动轮播的函数
if (interval) { // 如果定时器存在
clearInterval(interval); // 清除定时器
}
}
// 按钮点击事件
nextButton.addEventListener('click', function () { // 为下一张按钮添加点击事件监听器
nextSlide(); // 调用nextSlide函数切换到下一张
startAutoPlay(); // 重置自动轮播计时器,避免点击后立即自动切换造成的不良体验
});
prevButton.addEventListener('click', function () { // 为上一张按钮添加点击事件监听器
prevSlide(); // 调用prevSlide函数切换到上一张
startAutoPlay(); // 重置自动轮播计时器
});
// 指示器点击事件
indicators.forEach((indicator, index) => { // 为每个指示器点添加点击事件
indicator.addEventListener('click', function () { // 添加点击事件监听器
setActiveSlide(index); // 调用setActiveSlide函数切换到对应索引的幻灯片
startAutoPlay(); // 重置自动轮播计时器
});
});
// 当鼠标悬停在轮播图上时,暂停自动轮播
const carouselWrapper = document.querySelector('.carousel-wrapper'); // 获取轮播图容器元素
carouselWrapper.addEventListener('mouseenter', stopAutoPlay); // 鼠标进入时停止自动轮播
carouselWrapper.addEventListener('mouseleave', startAutoPlay); // 鼠标离开时恢复自动轮播
// 触摸事件支持(适用于移动设备)
let touchStartX = 0; // 存储触摸开始位置的X坐标
let touchEndX = 0; // 存储触摸结束位置的X坐标
carouselWrapper.addEventListener('touchstart', function (e) { // 添加触摸开始事件监听器
touchStartX = e.changedTouches[0].screenX; // 记录第一个触摸点的X坐标
stopAutoPlay(); // 停止自动轮播
}, { passive: true }); // 使用passive: true提高性能,表示不会调用preventDefault()
carouselWrapper.addEventListener('touchend', function (e) { // 添加触摸结束事件监听器
touchEndX = e.changedTouches[0].screenX; // 记录触摸结束时的X坐标
handleSwipe(); // 处理滑动事件
startAutoPlay(); // 恢复自动轮播
}, { passive: true }); // 使用passive: true提高性能
function handleSwipe() { // 定义处理滑动的函数
const swipeThreshold = 50; // 滑动阈值,需要超过这个距离才判定为有效滑动
if (touchEndX < touchStartX - swipeThreshold) { // 如果向左滑动超过阈值
// 向左滑动 -> 下一张
nextSlide(); // 切换到下一张幻灯片
} else if (touchEndX > touchStartX + swipeThreshold) { // 如果向右滑动超过阈值
// 向右滑动 -> 上一张
prevSlide(); // 切换到上一张幻灯片
}
}
});
效果

ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ
ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ