下面的轮播图是如何实现的?要逐行讲解清楚原理
html代码:
<div class="mr-slider mr-slider-default scoll" data-mr-flexslider id="demo-slider-0"> <div id="box"> <ul id="imagesUI" class="list"> <li class="current" style="opacity: 1;"><img src="images/ad1.png"></li> <li style="opacity: 0;"><img src="images/ad2.png" ></li> <li style="opacity: 0;"><img src="images/ad3.png" ></li> <li style="opacity: 0;"><img src="images/ad4.png" ></li> </ul> <ul id="btnUI" class="count"> <li class="current">1</li> <li class="">2</li> <li class="">3</li> <li class="">4</li> </ul> </div> </div> <div class="clear"></div>
js代码:
<script>
//alert(window.innerWidth);
var box=document.getElementById('box');
var imagesUI=document.getElementById('imagesUI');
var btnUI=document.getElementById('btnUI');
var imgs=imagesUI.getElementsByTagName('li');
var btn=btnUI.getElementsByTagName('li');
var i=index=0; //中间量,统一声明;
var play=null;
console.log(box,imgs,imgs,btn);//获取正确
autoPlay();//马上调用,我试过用window.onload调用这个方法,但是调用之后影响到了其他方法,使用autoPlay所以只能这样调用了
//div的鼠标移入移出事件
box.onmouseover=function(){
clearInterval(play);
};
box.onmouseout=function(){
autoPlay();
};
//自动轮播方法
function autoPlay(){
play=setInterval(function(){ //定时器处理
index++;
index>=imgs.length&&(index=0);
show(index);
},3000)
}
//图片切换方法
function show(a){
for(i=0;i<btn.length;i++ ){
btn[i].className=''; //显示当前设置按钮。
btn[a].className='current';
}
for(i=0;i<imgs.length;i++){ //把图片的效果设置和按钮相同
imgs[i].style.opacity=0;
imgs[a].style.opacity=1;
}
}
//切换按钮功能
for(i=0;i<btn.length;i++){
btn[i].index=i;
btn[i].onmouseover=function(){
show(this.index);
clearInterval(play);
}
}
</script>轮播图实现原理逐行详解
这是一个典型的淡入淡出轮播图,通过改变图片的透明度(opacity)来实现图片切换,同时配合底部按钮的高亮显示。
一、HTML 结构分析
html
<div class="mr-slider mr-slider-default scoll" data-mr-flexslider id="demo-slider-0"> <div id="box"> <!-- 图片列表 --> <ul id="imagesUI" class="list"> <li class="current" style="opacity: 1;"><img src="images/ad1.png"></li> <li style="opacity: 0;"><img src="images/ad2.png" ></li> <li style="opacity: 0;"><img src="images/ad3.png" ></li> <li style="opacity: 0;"><img src="images/ad4.png" ></li> </ul> <!-- 按钮列表(指示器) --> <ul id="btnUI" class="count"> <li class="current">1</li> <li class="">2</li> <li class="">3</li> <li class="">4</li> </ul> </div></div>
关键点
| 元素 | 作用 | 初始状态 |
|---|---|---|
#box | 轮播图容器,用于监听鼠标事件 | - |
#imagesUI .list li | 图片项,共4张 | 第1张透明1(可见),其余透明0(不可见) |
#btnUI .count li | 按钮指示器 | 第1个高亮(current),其余普通 |
透明度原理:opacity: 1 完全可见,opacity: 0 完全透明(不可见)。通过改变图片项的 opacity 实现淡入淡出切换。
二、JS 代码逐行详解
1、变量声明与元素获取
javascript
var box = document.getElementById('box');var imagesUI = document.getElementById('imagesUI');var btnUI = document.getElementById('btnUI');获取三个核心容器的 DOM 元素
box:轮播图容器(用于鼠标事件)imagesUI:图片列表容器btnUI:按钮列表容器
javascript
var imgs = imagesUI.getElementsByTagName('li');var btn = btnUI.getElementsByTagName('li');imgs:获取所有图片项(<li>),共 4 个btn:获取所有按钮项(<li>),共 4 个
javascript
var i = index = 0; // 中间量,统一声明var play = null;
i:循环计数器,用于for循环index:当前显示的图片索引(0、1、2、3)play:定时器变量,用于存储setInterval的返回值
javascript
console.log(box, imgs, btn); // 获取正确
控制台输出,验证元素是否获取成功
2、启动自动轮播
javascript
autoPlay(); // 马上调用
立即执行
autoPlay()函数,启动定时器注释说明:尝试过用
window.onload但会影响其他方法,所以直接调用
3、鼠标移入移出事件
javascript
box.onmouseover = function() {
clearInterval(play);};鼠标移入轮播图容器时,清除定时器
clearInterval(play):停止自动轮播目的:用户想要手动操作时,暂停自动切换
javascript
box.onmouseout = function() {
autoPlay();};鼠标移出轮播图容器时,重新启动自动轮播
调用
autoPlay()恢复定时器
4、自动轮播方法
javascript
function autoPlay() {
play = setInterval(function() {
index++;
index >= imgs.length && (index = 0);
show(index);
}, 3000)}逐行解释:
| 代码 | 含义 |
|---|---|
play = setInterval(...) | 启动定时器,每 3 秒执行一次,返回值存入 play |
index++ | 索引加 1(切换到下一张) |
index >= imgs.length && (index = 0) | 如果索引达到最后一张(4),则回到 0(第一张) |
show(index) | 调用 show 函数,切换到指定索引的图片 |
示例:
第1次:index=0 → 加1后 index=1 → show(1) → 显示第2张
第2次:index=1 → 加1后 index=2 → show(2) → 显示第3张
第3次:index=2 → 加1后 index=3 → show(3) → 显示第4张
第4次:index=3 → 加1后 index=4 → 判断后变为0 → show(0) → 回到第1张
5、图片切换方法
javascript
function show(a) {
// 1. 按钮样式切换
for (i = 0; i < btn.length; i++) {
btn[i].className = '';
btn[a].className = 'current';
}
// 2. 图片透明度切换
for (i = 0; i < imgs.length; i++) {
imgs[i].style.opacity = 0;
imgs[a].style.opacity = 1;
}}参数 a:要切换到第几张图片(0,1,2,3)
第一步:按钮样式切换
javascript
for (i = 0; i < btn.length; i++) {
btn[i].className = ''; // 清除所有按钮的 class
btn[a].className = 'current'; // 给当前按钮添加高亮 class}注意:这个循环写法有问题!
btn[a].className = 'current'每次循环都执行,效率低且逻辑混乱。
正确写法应该是:
javascript
// 先全部清空for (i = 0; i < btn.length; i++) {
btn[i].className = '';}// 再单独设置当前按钮btn[a].className = 'current';第二步:图片透明度切换
javascript
for (i = 0; i < imgs.length; i++) {
imgs[i].style.opacity = 0; // 所有图片设为透明
imgs[a].style.opacity = 1; // 当前图片设为可见}同样的问题:
imgs[a].style.opacity = 1在循环内重复执行 4 次
正确写法:
javascript
for (i = 0; i < imgs.length; i++) {
imgs[i].style.opacity = 0;}imgs[a].style.opacity = 1;6、手动点击按钮切换
javascript
for (i = 0; i < btn.length; i++) {
btn[i].index = i; // 给每个按钮添加自定义属性 index,记录自己的索引
btn[i].onmouseover = function() {
show(this.index); // 切换到对应图片
clearInterval(play); // 停止自动轮播
}}逐行解释:
| 代码 | 含义 |
|---|---|
btn[i].index = i | 给每个按钮添加一个 index 属性,值为 0、1、2、3 |
btn[i].onmouseover = function() { ... } | 绑定鼠标移入事件 |
show(this.index) | 调用 show 函数,this.index 就是当前按钮的索引 |
clearInterval(play) | 清除定时器,停止自动轮播 |
为什么需要 btn[i].index = i?
如果不设置,在回调函数中无法知道当前按钮是第几个
直接用
i会变成循环结束后的值(始终为 4),这是 JavaScript 闭包的经典问题
三、完整执行流程图
text
┌─────────────────────────────────────────────────────────────────┐ │ 页面加载 │ │ ↓ │ │ autoPlay() 启动 │ │ ↓ │ │ setInterval 每 3 秒执行一次 │ │ ↓ │ │ index++ → 切换到下一张 │ │ ↓ │ │ show(index) 执行 │ │ ↓ │ │ ┌─────────────────────────────────────┐ │ │ │ 1. 清空所有按钮的 class │ │ │ │ 2. 给当前按钮添加 current class │ │ │ │ 3. 所有图片 opacity 设为 0 │ │ │ │ 4. 当前图片 opacity 设为 1 │ │ │ └─────────────────────────────────────┘ │ │ ↓ │ │ 图片切换完成 │ └─────────────────────────────────────────────────────────────────┘ 同时,用户可交互: ┌─────────────────────────────────────────────────────────────────┐ │ 鼠标移入轮播图 │ │ ↓ │ │ clearInterval(play) → 停止自动轮播 │ │ ↓ │ │ 手动点击按钮 │ │ ↓ │ │ show(点击的索引) → 切换图片 │ │ ↓ │ │ clearInterval(play) → 再次停止自动轮播 │ │ ↓ │ │ 鼠标移出轮播图 │ │ ↓ │ │ autoPlay() → 重新启动 │ └─────────────────────────────────────────────────────────────────┘
四、代码存在的问题及改进
| 问题 | 说明 | 改进 |
|---|---|---|
| 循环中重复赋值 | show() 函数中在循环内重复设置当前项 | 将当前项设置移到循环外 |
| 索引依赖 | menu[3] 依赖 HTML 格式 | 用 querySelector 代替 |
| 全局变量过多 | i 声明在全局 | 使用 let 局部变量 |
| 无防抖 | 快速移入移出可能多次触发 | 添加防抖处理 |
五、总结
| 核心功能 | 实现方式 |
|---|---|
| 自动轮播 | setInterval 定时器,每 3 秒 index++ 并调用 show() |
| 图片切换 | 改变图片的 opacity 属性(0 透明 / 1 可见) |
| 按钮高亮 | 改变按钮的 className(添加/移除 current) |
| 鼠标交互 | mouseover 暂停,mouseout 恢复 |
| 手动切换 | 点击按钮时调用 show() 并清除定时器 |
一句话总结:轮播图通过定时器自动递增索引,改变图片的透明度实现淡入淡出切换,同时更新底部按钮的高亮状态;鼠标移入时暂停自动播放,移出时恢复,点击按钮可直接跳转到对应图片