写在前面
是的,这个轮播图我看了一天的时间,网上找说明,外加请教别人,自己动手试着写写,昨天看了一下午,夜里又简单想了一下整个流程。终于今天上午开始动手写,磕磕绊绊,跌跌撞撞,完整的轮播让我给实现了。
总的来说,算是完成了,为啥要说算是呢,因为自己在独立地写的过程中还是会出现一些问题,就会看别人怎么写的,怎么实现的,再去对比一下自己的思路。遇到问题,思考问题,再到解决问题,是个需要不断重复的过程,只有这样,才会让自己熟练,时间长了,再遇到问题知道如何解决,从哪些地方去检查。
emmmmmmm,简单的学习心得分享完毕,开始撸思路,撸代码吧。
轮播图
轮播图功能需求:
1. 鼠标经过/离开轮播图时 左右按钮的显示/隐藏
2. 点击圆点时,圆度变为当前状态;图片切换
3. 左右按钮点击时,轮播图片
4. 图片轮播时 下方的圆点也跟着切换
5. 鼠标放上焦点图时 图片停止自动轮播 ; 鼠标离开时 图片自动轮播
需要注意的是,页面一开始图片就是轮播着的
优化的地方:
1. 增加节流阀:
当连续点击按钮时,一张图片没有轮播完就会出现下一张。增加的节流阀的目的就是解决上面所叙述的问题。一般节流阀就是两种操作,关闭节流阀(锁函数),打开节流阀(开函数)。
2. 提取代码相同的部分,单独作为一个函数,进行调用。还有就是把一些简单的if语句的判断可以使用三元表达式来代替
无缝轮播的思想
无缝轮播的布局:把放轮播图的ul中的第一个孩子li,复制一份放到ul的最后。
轮播具体实现的过程:正常的话,用户点击按钮进行图片的轮播,当用户看到最后一张图片(其实是我们布局中的倒数第二张)时,点击右侧按钮的时候,用户看到的是第一张图片,其本质是用户看到了我们布局中的最后一张,因为这一张图是我们复制的第一张图,与此同时,我们悄悄的把ul瞬间回到原位置(left = 0),制造假象,让用户以为是第一张图片,其实是我们布局中的最后一张。当用户再点击时,因为此时ul已经瞬间移回到原来的位置,再点击向右轮播的按钮,ul就按照正常的轮播到第二张图片。这样就实现了无缝轮播。
这是轮播图中比较重要的一个思想。思路解决了 ,咱们就看代码吧。
代码里面有很详细的解释,可以认真看看的。
JS部分
// 轮播图的需求:
// 1. 鼠标经过/离开轮播图时 左右按钮的显示/隐藏
// 2. 点击圆点时,圆度变为当前状态;图片切换
// 3. 左右按钮点击时,轮播图片
// 4. 图片轮播时 下方的圆点也跟着切换
// 5. 鼠标放上焦点图时 图片停止自动轮播 ; 鼠标离开时 图片自动轮播
// 需要注意的是,页面一开始图片就是轮播着的
window.addEventListener('load', function () {
// 1. 鼠标经过轮播图时 按钮的显示和隐藏
// 获取事件源
var focus = document.querySelector('.focus');
var arrowL = document.querySelector('.arrow-l');
var arrowR = document.querySelector('.arrow-r');
var ol = document.querySelector('.circle');
var ul = focus.querySelector('ul');
var focusWidth = focus.offsetWidth;
focus.addEventListener('mouseenter', function () {
arrowL.style.display = 'block';
arrowR.style.display = 'block';
clearInterval(carousel);
carousel = null;
})
focus.addEventListener('mouseleave', function () {
arrowL.style.display = 'none';
arrowR.style.display = 'none';
// 鼠标离开 自动轮播
carousel = setInterval(function () {
arrowR.click();
}, 3000)
})
// 2.点击圆点部分
// 圆点的个数应该是与图片的个数是一致的,所以 应该根据ul中的li的个数动态创建圆点的个数
// js需要写的具有一定的动态性 改变结构 时 js可以动态生成
for (var i = 0; i < ul.children.length; i++) {
// (1)创建圆点
var li = document.createElement('li');
// (2)添加到ol中
ol.appendChild(li);
// 设置一个变量 用来记录当前圆点的索引号 后面与图片位置对应显示
li.setAttribute('index', i);
// (3).点击圆点的事件效果 应该在创建之后就绑定事件
li.addEventListener('click', function () {
// (4).被点击的圆点 变成当前状态
// 干掉所有人 ol.children.length所有小圆点的个数
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下我自己 当前点击的圆点
this.className = 'current';
// (5). 点击时图片轮播
// 获得当前圆点的索引号
var currentIndex = this.getAttribute('index');
// 轮播到哪个li 把当前图片对应的圆点的索引号 给点击的次数
// 是保持圆点 按钮点击次数 图片对应一致
clickCount = currentIndex;
circleMove = currentIndex;
// ul移动的距离 圆点索引号*焦点图的宽度
animate(ul, -currentIndex * focusWidth);
})
}
// 默认设置第一个圆点为当前
ol.children[0].className = 'current';
// 无缝轮播:把ul中的图片复制一份到ul的最后。当用户点击到最后一张,就是我们的倒数第二张
// 用户再点击时 看到的是第一张的图片 其实是我们复制了第一张到ul的最后,所以用户看到的实际上是我们复制的那一张图
// 这时当用户再点击时 我们迅速把ul移回原位left=0,从头开始 再按照正常的轮播到第二张
// 克隆节点在创建小圆点的后面 因为克隆出来的节点不需要小圆点
// 复制ul第一个li放到最后 ul.children[0].cloneNode(true)深拷贝
var firstImg = ul.children[0].cloneNode(true);
ul.appendChild(firstImg);
// 点击按钮事件
// 点击右侧按钮 图片向左轮播 点击一次 图片(ul)移动一个图片的距离
// ul移动的距离 = 点击次数*焦点图的宽度 与上面点小圆点的效果类似
// 设置一个变量记录 点击的次数 点击一次图片滚动一次
var clickCount = 0;
// 记录圆点的位置 控制圆点的播放
var circleMove = 0;
// 节流阈值:为了防止点击过快图片没有轮播完就结束的情况
var flag = true;
// 3.右侧按钮点击
arrowR.addEventListener('click', function () {
if (flag) {
// 先锁住函数 当动画执行完毕之后 再解锁
flag = false; // 关闭节流阀
// (1) 当ul走到最后 我们复制的那一张图片时:ul的left = 0;迅速复原ul
if (clickCount == ul.children.length - 1) {
ul.style.left = 0;
clickCount = 0; // 点击置0
}
clickCount++;
animate(ul, -clickCount * focusWidth, function () {
flag = true; // 打开节流阀
});
// (2) 图片轮播时 圆点也在变化
circleMove++;
// 当圆点到最后一个4 也就是图片轮播到我们复制的哪一个图片时 圆点从头开始
if (circleMove == ol.children.length) {
circleMove = 0
}
// circleMove == ol.children.length - 1 ? 0 : circleMove;
// 调用函数 排他思想
circleVisible();
}
})
// 4.左侧按钮点击
arrowL.addEventListener('click', function () {
if (flag) {
flag = false;
// (1) 当ul是第一张图片时 点击时应轮播到倒数第二张
if (clickCount == 0) {
ul.style.left = -clickCount * focusWidth + 'px';
clickCount = ul.children.length - 1; // 点击数也回到图片对应的点击数
}
clickCount--;
animate(ul, -clickCount * focusWidth, function () {
flag = true;
});
// (2) 图片轮播时 圆点也在变化
circleMove--;
// 点击时 如果 circleMove < 0 说明是第一张图片 小圆点要从第4个开始 (索引号3)
if (circleMove < 0) {
circleMove = ol.children.length - 1
}
// circleMove < 0 ? ol.children.length - 1 : circleMove;
// 调用函数 排他思想
circleVisible();
}
})
// 5.鼠标经过时 设置定时器 自动轮播图片
// 自动轮播的效果 与点击右侧按钮的效果一样
// 即可以使用手动调取 右侧按钮点击事件
var carousel = setInterval(function autoCarousel() {
arrowR.click();
}, 3000)
// 排他
function circleVisible() {
// 干掉所有人
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下自己
ol.children[circleMove].className = 'current';
}
})
结构部分
这里有需要注意的一点,轮播图用到了之前封装的动画函数,需要引入动画的js文件,动画的js文件要在页面的js文件之前引入,因为动画js是依赖于页面的js文件的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./css/lb.css">
<!-- 依赖于lb.js 因为只有在有js文件时才会引入动画函数 所以要在前面引入 -->
<script src="./js/animate.js"></script>
<script src="./js/lb.js"></script>
</head>
<body>
<div class="w">
<div class="focus">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow-l">
</a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow-r"></a>
<!-- 核心的滚动区域 -->
<ul>
<li>
<a href="#"><img src="upload/focus.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="upload/focus1.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="upload/focus2.jpg" alt=""></a>
</li>
<!-- 注意这是第一张图片复制过来的 -->
<li>
<a href="#"><img src="upload/focus3.jpg" alt=""></a>
</li>
</ul>
<!-- 小圆圈 -->
<ol class="circle">
</ol>
</div>
</div>
</body>
</html>
ok,轮播图克服掉了。
春意盎然,我的寒假还在继续。。。。。。