一、案例
小米官网
二、功能需求
1、结构:轮播图片+底部导航条/小圆点+左右切换按钮
2、图片自动轮播,底部导航条/小圆点跟着切换
3、点击切换按钮,切换图片
4、点击底部导航条/小圆点,切换图片
三、html结构
1、结构简图
2、html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图</title>
<body>
<!-- 轮播区间 -->
<div class="swiper-container">
<!-- 轮播图片 -->
<ul class="swiperLists">
<li class="swiper-li"><a href="#"><img src="../static/images/swiperImage/swiper1.jpg"></a></li>
<li class="swiper-li"><a href="#"><img src="../static/images/swiperImage/swiper2.jpg"></li>
<li class="swiper-li"><a href="#"><img src="../static/images/swiperImage/swiper3.jpg"></li>
</ul>
<!-- 左按钮 -->
<a href="#" class="left"><</a>
<!-- 右按钮 -->
<a href="#" class="right">></a>
<!-- 导航条:有序列表 -->
<ol class="swiper-nav">
<li class="current"></li>
<li class="others"></li>
<li class="others></li>
</ol>
</div>
</body>
</html>
四、css样式设置外观和布局
1、将所有元素margin,padding重置为0
* {
padding: 0;
margin: 0;
}
2、去除列表样式
ul,
ol {
list-style: none;
}
3、轮播区域样式:宽高、相对定位(作为父级)、超出部分隐藏
/* 轮播区域样式 */
.swiper-container {
width: 1422px;
height: 600px;
position: relative;
overflow: hidden;
}
4、轮播图片的样式:
给图片集设置宽度1000%,使其能容纳所有图片。
给图片设置浮动,使其水平排列
/* 轮播图片样式 */
.swiper-container .swiperLists {
width: 1000%;
}
.swiper-container .swiper-li {
float: left;
}
5、左右按钮样式
给他们添加绝对定位,将他们定位到轮播区域的固定位置。
并添加hover,鼠标悬停时更改颜色。
.left,
.right {
position: absolute;
top: 280px;
color: #fff;
text-decoration: none;
font-weight: 700;
font-size: 26px
}
.left {
left: 50px;
}
.right {
right: 50px;
}
.left:hover {
/* 鼠标悬停在左右按钮时变色 */
color: #FF6900;
}
.right:hover {
color: #FF6900;
}
6、顶部导航条样式
导航条的容器设置绝对定位
容器内每个导航条设置浮动,使其水平排列
.swiper-nav { /* 导航条容器 */
position: absolute;
left: 600px;
bottom: 20px;
}
.swiper-nav li { /* 单个导航条 */
float: left;
width: 100px;
height: 3px;
background-color: #C9C8C7;
}
.swiper-nav .others:hover { /* 悬停变色 */
background-color: #7E7E7E;
}
.swiper-nav .current { /* 当前导航条为橙色 */
background-color: #FF6900;
}
7、引入css
<link rel="stylesheet" type="text/css" href="../css/轮播图.css" />
8、效果
五、js实现动态效果
功能一:鼠标移到轮播区域时,显示左右切换按钮,鼠标离开时隐藏
1、添加监听事件:load事件(页面加载完毕时执行),mouseenter事件(鼠标进入时执行),mouseleave事件(鼠标离开时执行)
window.addEventListener("load", function () {
//1.获取元素
var swiperContainer = this.document.querySelector(".swiper-container");
var left = this.document.querySelector(".left");
var right = this.document.querySelector(".right");
//2.鼠标进入轮播区域:显示按钮
swiperContainer.addEventListener("mouseenter", function () {
left.style.display = "block"
right.style.display = "block"
})
//3.鼠标离开轮播区域,隐藏按钮
swiperContainer.addEventListener("mouseleave", function () {
left.style.display = "none"
right.style.display = "none"
})
2、在html中引用js代码
<script src="../js/轮播图.js"></script>
3、效果
功能二:点击按钮切换图片
1、给swiperLists加定位,便于后续添加动画
2、新建animate.js文件,写动画函数。
- offsetLeft获取元素左边界偏移量,判断元素是否到达目标点
- 若没到达目标点,修改元素left属性使其移动,每次移动一个步长,添加计时器使其一直移动直到到达目标点
function animate(obj, target) { //参数:运动的对象,目标点
clearInterval(obj.timer); //清除当前对象身上的计时器
obj.timer = setInterval(function () { //添加新计时器
var step = (target - obj.offsetLeft) / 10; //动态步长,先快后慢
// 确保步长是整数
//如果step大于0,math.ceil向上取整,即0.5取1
//如果step小于0,math.floor向下取整,即-0.5取-1
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) { //offsetLeft:元素左边界偏移量
clearInterval(obj.timer); //到达目标点停止运动,即清除计时器
}
//加法运算结果取整数,如果步长有小数的话会有误差
obj.style.left = (obj.offsetLeft + step) + "px"; //运动到目标位置
}, 10)
}
- 遗留问题(求指教):怎样实现匀速移动?比如图片宽度1422,步长1422/10=144.2,每次移动144.2px,计时器循环10次移动到目标位置。obj.style.left = (obj.offsetLeft + step) + "px";这个运算会自动将step的小数位抹去,无法实现移动小数位步长
function animate(obj, target) { //参数:运动的对象,目标点
clearInterval(obj.timer); //清除当前对象身上的计时器
var step = (target - obj.offsetLeft) / 10; //固定步长
console.log("step=" + step);
obj.timer = setInterval(function () { //添加新计时器
if (obj.offsetLeft == target) { //offsetLeft:元素左边界偏移量
clearInterval(obj.timer); //停止运动,即清除计时器
}
obj.style.left = (obj.offsetLeft + step) + "px"; //运动到目标位置
console.log("offsetLeft=" + obj.offsetLeft);
}, 10)
}
3、在html中引入animate.js(要写在轮播图.js前面,因为轮播图.js中使用了动画函数)
<!-- 引入js -->
<script src="../js/animate.js"></script>
<script src="../js/轮播图.js"></script>
4、在轮播图.js中给right按钮添加点击事件。offsetWidth获取图片宽度,再乘以索引值就是移动距离。
//1.获取元素
var swiperLists = this.document.querySelector(".swiperLists");
var imgWidth = swiperContainer.offsetWidth; //图片宽度
//2.right按钮的点击事件
right.addEventListener("click", function () {
index++; //点击下一张,图片索引值加一
animate(swiperLists, -(index * imgWidth));
})
5、难点:实现循环轮播
- 将第一张图片复制一份到列表末尾
- 调用animate函数移动到下一张图片
- 每次点击下一张按钮时,先判断当前图片是否为克隆图片,若为克隆图片,将当前图片切换为第一张图片。这样,当为最后一张图片时,点击right按钮,滑动切换到克隆图(视觉效果为第一张);再次点击right按钮,快速从克隆图切换到第一张图(视觉上看不出来),然后第一张的下一张为第二张,滑动切换到第二张。
//right按钮的点击事件
var firstImg = swiperLists.children[0].cloneNode(true); //克隆swiperLists第一个孩子,即第一张图片
swiperLists.appendChild(firstImg); //将克隆图片添加到swiperLists末尾
right.addEventListener("click", function () { //点击下一张按钮
if (index == swiperLists.children.length - 1) { //先判断当前是否为克隆图片
swiperLists.style.left = 0; //若为克隆图片,将图片切换到第一张
index = 0;
}
index++; //图片索引值加一
animate(swiperLists, -(imgWidth * index)); //移动到下一张
})
6、left按钮同理
- 先判断是否为第一张图片
- 若为第一张图片,将当前图片切换为克隆图片
- 再调用animate函数移动到上一张(第一张→克隆图片→最后一张,由于克隆图片和第一张图片一样,所以视觉效果为:第一张→最后一张)
//left按钮的点击事件
left.addEventListener("click", function () { //点击上一张按钮
if (index == 0) { //先判断当前是否是第一张图片
index = swiperLists.children.length - 1; //3
swiperLists.style.left = -index * imgWidth + "px"; //若为第一张图片,将图片切换到克隆图片
}
index--; //图片索引值减一 2
animate(swiperLists, -index * imgWidth); //移动到上一张(克隆图片的上一张为:最后一张图片)
})
功能三:根据图片数量自动生成导航条
1、删除<ol>标签下的<li>,便于后续生成
<!-- 导航条:有序列表 -->
<ol class="swiper-nav">
</ol>
2、动态生成导航条
//1、根据类名获取<ol>标签
var swiperNav = this.document.querySelector(".swiper-nav");
//2、创建<li>标签,插入<ol>中
for (i = 0; i < swiperLists.children.length; i++) {
var li = document.createElement("li"); //创建li标签
li.className = "others"; //给li标签添加class属性
swiperNav.appendChild(li); //将li标签插入到swiperNav中
}
3、效果
功能四:点击按钮切换图片,导航条随图片改变
1、index为图片索引值,所以根据index值切换导航条。注意克隆图片的原型为第一张图片,当显示克隆图片时切换到第一个导航条。创建changeNav()函数实现切换导航条功能。
//图片与导航条对应
function changeNav() {
for (j = 0; j < swiperNav.children.length; j++) { //移除所有导航条的class属性
swiperNav.children[j].className = "others";
}
if (index == swiperLists.children.length - 1) { //如果是克隆图片
swiperNav.children[0].className = "current"; //因为克隆的是第一张图,所以第一个导航条被选中
console.log("克隆图片");
}
else {
console.log("普通图片");
console.log(index);
swiperNav.children[index].className = "current"; //当前导航条设置为选中状态
}
}
2、动态生成导航条后调用changeNav()方法,使第一个导航条默认选中
changeNav();
3、在之前写的right和left按钮的点击事件中调用changeNav()方法,使导航条随按钮点击而切换。
4、效果
功能五:点击导航条切换图片
1、给导航条添加点击事件,当导航条被点击时,根据其num值切换对应图片
li.addEventListener("click", function () { //导航条点击事件
for (j = 0; j < swiperNav.children.length; j++) { //移除所有导航条的class属性
swiperNav.children[j].className = "others";
console.log("remove");
}
this.className = "current"; //被点击的导航条选中
var n = this.getAttribute("num"); //获取被点击导航条的num值
animate(swiperLists, -(n * imgWidth)); //根据num值切换图片
})
2、效果
功能六:自动轮播
1、添加计时器,每隔一段时间执行right按钮的点击事件
//自动轮播
var timer = this.setInterval(function () {
right.click();
}, 5000)
六、完整代码
1、项目结构
2、html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图</title>
<!-- 引入css -->
<link rel="stylesheet" type="text/css" href="../css/轮播图.css" />
<!-- 引入js -->
<script src="../js/animate.js"></script>
<script src="../js/轮播图.js"></script>
</head>
<body>
<!-- 轮播区间 -->
<div class="swiper-container">
<!-- 轮播图片 -->
<ul class="swiperLists">
<li class="swiper-li">
<a href="#"><img src="../static/images/swiperImage/swiper1.jpg"></a>
</li>
<li class="swiper-li">
<a href="#"><img src="../static/images/swiperImage/swiper2.jpg"></a>
</li>
<li class="swiper-li">
<a href="#"><img src="../static/images/swiperImage/swiper3.jpg"></a>
</li>
</ul>
<!-- 左按钮 -->
<a href="#" class="left"><</a>
<!-- 右按钮 -->
<a href="#" class="right">></a>
<!-- 导航条:有序列表 -->
<ol class="swiper-nav">
</ol>
</div>
</body>
</html>
3、css代码
* {
padding: 0;
margin: 0;
}
/* 轮播区域样式 */
.swiper-container {
width: 1422px;
height: 600px;
position: relative;
overflow: hidden;
}
/* 去除列表的样式 */
ul,
ol {
list-style: none;
}
/* 轮播图片样式 */
.swiper-container .swiperLists {
width: 1000%;
position: absolute;
left: 0;
}
.swiper-container .swiper-li {
float: left;
}
/* 左右按钮样式 */
.left,
.right {
position: absolute;
top: 280px;
color: #fff;
text-decoration: none;
font-weight: 700;
font-size: 26px
}
.left {
left: 50px;
}
.right {
right: 50px;
}
.left:hover {
/* 鼠标悬停在左右按钮时变色 */
color: #FF6900;
}
.right:hover {
color: #FF6900;
}
/* 导航条样式 */
.swiper-nav {
/* 导航条容器 */
position: absolute;
left: 600px;
bottom: 20px;
}
.swiper-nav li {
/* 单个导航条 */
float: left;
width: 100px;
height: 3px;
background-color: #C9C8C7;
}
.swiper-nav .others:hover {
/* 悬停变色 */
background-color: #7E7E7E;
}
.swiper-nav .current {
/* 当前导航条为橙色 */
background-color: #FF6900;
}
4、animate.js代码
function animate(obj, target) { //参数:运动的对象,目标点
clearInterval(obj.timer); //清除当前对象身上的计时器
obj.timer = setInterval(function () { //添加新计时器
var step = (target - obj.offsetLeft) / 10; //动态步长,先快后慢
// 确保步长是整数
//如果step大于0,math.ceil向上取整,即0.5取1
//如果step小于0,math.floor向下取整,即-0.5取-1
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) { //offsetLeft:元素左边界偏移量
clearInterval(obj.timer); //停止运动,即清除计时器
}
//加法运算结果取整数,如果步长有小数的话会有误差
obj.style.left = (obj.offsetLeft + step) + "px"; //运动到目标位置
}, 10)
}
5、轮播图.js代码
window.addEventListener("load", function () {
// 定义全局变量
var index = 0; //图片索引值
//1.获取元素
var swiperContainer = this.document.querySelector(".swiper-container");
var left = this.document.querySelector(".left");
var right = this.document.querySelector(".right");
var swiperLists = this.document.querySelector(".swiperLists");
var swiperNav = this.document.querySelector(".swiper-nav");
var imgWidth = swiperContainer.offsetWidth; //图片宽度
//动态生成导航条
for (i = 0; i < swiperLists.children.length; i++) {
var li = document.createElement("li"); //创建li标签
li.className = "others"; //给li标签添加class属性
li.setAttribute("num", i); //给li标签添加索引值
swiperNav.appendChild(li); //将li标签插入到swiperNav中
console.log("create");
li.addEventListener("click", function () { //导航条点击事件
for (j = 0; j < swiperNav.children.length; j++) { //移除所有导航条的class属性
swiperNav.children[j].className = "others";
console.log("remove");
}
this.className = "current"; //被点击的导航条选中
var n = this.getAttribute("num"); //获取被点击导航条的num值
animate(swiperLists, -(n * imgWidth)); //根据num值切换图片
})
}
//图片与导航条对应
function changeNav() {
for (j = 0; j < swiperNav.children.length; j++) { //移除所有导航条的class属性
swiperNav.children[j].className = "others";
}
if (index == swiperLists.children.length - 1) { //如果是克隆图片
swiperNav.children[0].className = "current"; //因为克隆的是第一张图,所以第一个导航条被选中
console.log("克隆图片");
}
else {
console.log("普通图片");
console.log(index);
swiperNav.children[index].className = "current"; //当前导航条设置为选中状态
}
}
changeNav();
//2.鼠标进入轮播区域:显示按钮
swiperContainer.addEventListener("mouseenter", function () {
left.style.display = "block"
right.style.display = "block"
})
//3.鼠标离开轮播区域,隐藏按钮
swiperContainer.addEventListener("mouseleave", function () {
left.style.display = "none"
right.style.display = "none"
})
//4.right按钮的点击事件
var firstImg = swiperLists.children[0].cloneNode(true); //克隆swiperLists第一个孩子,即第一张图片
swiperLists.appendChild(firstImg); //将克隆图片添加到swiperLists末尾
right.addEventListener("click", function () { //点击下一张按钮
if (index == swiperLists.children.length - 1) { //先判断当前是否为克隆图片
swiperLists.style.left = 0; //若为克隆图片,将图片切换到第一张
index = 0;
}
index++; //图片索引值加一
animate(swiperLists, -(imgWidth * index)); //移动到下一张
changeNav();
})
//5.left按钮的点击事件
left.addEventListener("click", function () { //点击上一张按钮
if (index == 0) { //先判断当前是否是第一张图片
index = swiperLists.children.length - 1; //3
swiperLists.style.left = -index * imgWidth + "px"; //若为第一张图片,将图片切换到克隆图片
}
index--; //图片索引值减一 2
animate(swiperLists, -index * imgWidth); //移动到上一张(克隆图片的上一张为:最后一张图片)
changeNav();
})
//自动轮播
var timer = this.setInterval(function () {
right.click();
}, 5000)
})