之前我发过了用CSS的动画效果实现的轮播图代码,这次我来用JS实现一份更加完美的轮播图效果。
首先,准备一个工程,里面放HTML文件index.html;CSS文件index.css;JS文件index.js.
话不多说,代码如下:
代码:
1.index.html
代码量不多,而且此处注释都写得比较明白了,我就不多说了,不过要注意的就是我这里的图片路径还有css文件和js文件的路径和你们不一样,用的时候注意修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css">
<script src="js/index.js"></script>
</head>
<body>
<div class="swiper">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow-l">
<
</a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow-r">
>
</a>
<!-- 图片 -->
<ul class="banner">
<li><img src="images/001.webp" alt="" /></li>
<li><img src="images/002.webp" alt="" /></li>
<li><img src="images/004.webp" alt="" /></li>
<li><img src="images/005.jpg" alt="" /></li>
<li><img src="images/006.png" alt="" /></li>
<li><img src="images/007.jpg" alt="" /></li>
</ul>
<!-- 小圆圈 -->
<!-- 小圆点不写死,后面由JS根据图片数量自动生成 -->
<ol class="circle">
</ol>
</div>
</body>
</html>
2.index.css
CSS也不多讲了,都是简单的布局,和之前用的CSS效果比起来只是多了点内容,注释也写的非常清楚
/* 标识符定义全局样式 */
* {
padding: 0;
margin: 0;
text-decoration: none;
color: rgb(255, 255, 255);
box-sizing: border-box;
}
/* 设置主要盒子位置 */
.swiper {
/* 相对定位 */
position: relative;
top: 15%;
width: 900px;
height: 580px;
/* 超出盒子隐藏 */
overflow: hidden;
margin: 10px auto;
}
/* 设置图片上左右箭头的样式 */
.arrow-r,
.arrow-l {
/* 先设置隐藏,在JS样式中设置当鼠标移动到图片上再显示出来 */
display: none;
position: absolute;
width: 30px;
height: 40px;
background-color: rgba(0, 0, 0, .4);
line-height: 30px;
text-align: center;
right: 0;
top: 240px;
font-size: 30px;
color: #fff;
/* 让箭头的z轴位置更高,显示在图片上层 */
z-index: 2;
}
.arrow-l {
left: 0;
/* 将箭头边框设置为圆 */
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
}
.arrow-r {
right: 0;
border-top-left-radius: 50%;
border-bottom-left-radius: 50%;
}
/* 鼠标经过箭头后颜色变化 */
.swiper a:hover {
color: red;
}
/* 设置图片下方小圆点的样式与位置 */
.circle {
position: absolute;
left: 355px;
bottom: 50px;
/* 让小圆点的z轴位置更高,显示在图片上层 */
z-index: 2;
}
/* 设置小圆点的样式且将其横排浮动 */
.swiper .circle li {
float: left;
display: block;
width: 15px;
height: 15px;
border: 3px solid #ff4d07;
border-radius: 50%;
margin-right: 20px;
/*鼠标经过显示小手*/
cursor: pointer;
}
/* 给小圆点加一个背景,先不添加,给JS代码中调用此类 */
.current {
background-color: #fff;
}
/* 设置图片位置 */
.banner {
position: absolute;
top: 0;
left: 0;
/* 宽度设大,让其子元素能够横排浮动 */
width: 3000%;
}
/* 让图片横排浮动 */
.banner li {
float: left;
width: 900px;
height: 580px;
list-style-type: none;
}
.banner li img {
width: 100%;
height: 100%;
}
3.index.js
js代码这方面用的技术还是比较多的,我这里如果一一说明就太多了,关键代码的注释我也写的比较清楚了,如果类名和我的html码中不一样,这里一定要记得修改
window.addEventListener('load', function () {
// 轮播图
// 1. 获取元素
var arrow_l = this.document.querySelector('.arrow-l');
var arrow_r = this.document.querySelector('.arrow-r');
var swiper = document.querySelector('.swiper');
var swiperWidth = swiper.offsetWidth;
var ul = swiper.querySelector('ul');
var ol = swiper.querySelector('.circle');
// 2. 鼠标经过swiper 就显示隐藏左右按钮
swiper.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);
timer = 'null';
})
swiper.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(function () {
//手动调用点击事件
arrow_r.click();
}, 2000);
})
// 3. 动态生成小圆圈 有几张图片,我就生成几个小圆圈
for (var i = 0; i < ul.children.length; i++) {
// 创建一个小li
var li = document.createElement('li');
// 把小li插入到ol 里面
ol.appendChild(li);
// 记录当前小圆圈的索引号 通过自定义属性来做
li.setAttribute('index', i);
// 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener('click', function () {
// 干掉所有人 把所有的小li 清除 current 类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下我自己 当前的小li 设置current 类名
this.className = 'current';
var index = this.getAttribute('index');
var step = -swiperWidth * index;
animate(ul, step);
// 当我们点击了某个小li 就要把这个li 的索引号给 num
num = index;
// 当我们点击了某个小li 就要把这个li 的索引号给 circle
circle = index;
// num = circle = index;
})
// 5. 点击小圆圈,移动图片 当然移动的是 ul
// ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值
// 当我们点击了某个小li 就拿到当前小li 的索引号
}
// 把ol里面的第一个小li设置类名为 current
ol.children[0].className = 'current';
// 6. 克隆第一张图片(li)放到ul 最后面
var frist = ul.children[0].cloneNode(true);
ul.appendChild(frist);
var num = 0;
var circle = 0;
// 7. 点击右侧按钮, 图片滚动一张
// flag 节流阀
var flag = true;
arrow_r.addEventListener('click', function () {
if (flag) {
flag = false;
// 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
if (num == ul.children.length - 1) {
num = 0;
ul.style.left = 0;
}
num++;
animate(ul, -swiperWidth * num, function () {
flag = true;
});
circle++;
if (circle == ol.children.length) {
circle = 0;
}
circleChange();
}
})
// 7. 点击左侧按钮, 图片滚动一张
arrow_l.addEventListener('click', function () {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * swiperWidth + 'px';
}
num--;
animate(ul, -swiperWidth * num, function () {
flag = true;
});
circle--;
if (circle < 0) {
circle = 3;
}
circleChange();
}
// 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
})
// 封装左右两键的排他函数
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[circle].className = 'current';
}
// 自动播放
var timer = setInterval(function () {
arrow_r.click();
}, 2000)
})
// 图片移动函数封装
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
以上便是所有代码,分别放在三个文件中,代码量还是比较多的,其实很多东西没有必要,只是我自己添加上去的,如果有什么可以更加优化的地方,还望各位大佬多加指点