z案例:网页轮播图
也称为焦点图
功能需求:
鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
点击右侧按钮一次,图片往左播放一次,依此类推,左按钮同理
图片播放的同时,下面小圆圈模块跟随一起变化
点击小圆圈,可以播放相应图片
鼠标不经过轮播图,轮播图也会自动播放
鼠标经过轮播图模块,自动播放停止
其中模块:
动态生成小圆圈:
核心思路:小圆圈的个数要和图片张数一致
首先得到ul里面图片的数量,(图片放入li里面,所以是li的个数)
利用循环动态生成小圆圈(这个小圆圈要放入ol里面)
创建节点 createElement (’ li ')
插入节点 ol.appendChild ( li )
第一个小圆圈添加类名li.children[0].className = "current";
点击小圆圈,可以播放相应图片
排他思想: 点击当前小圆圈,就添加current 类,其余的就移除这个类
点击小圆圈滚动图片
此时用到 animate 动画函数,将js文件引入,因为index.js 依赖 animate.js 所以 animate.js 必须写到 index.js 上面
使用动画函数的前提,该元素必须有定位
是ul 移动 ,不是 li
滚动图片核心算法:点击某个小圆圈,就让图片滚动小圆圈的索引号乘以图片的宽度(是负值)作为 ul 的移动距离
此时需要知道小圆圈的索引号,我们可以在生成小圆圈的时候给他设置一个自定义属性,点击的时候获取这个自定义属性即可
点击右侧按钮一次,图片往左播放一次
声明一个变量 num 点击一次 自增一 ,让这个变量乘以图片宽度,就是ul的滚动距离
图片滚动到最后一张时,用到图片无缝滚动
图片无缝滚动原理:把ul 的第一个 li 复制一份,放到 ul 的最后面
当图片滚动到最后一张时,让ul快速的,不做动画地跳到最左侧:left 为 0
同时把 num 赋值为 0 ,重新开始滚动
克隆第一张图片
克隆ul 第一个 li cloneNode() 加 true 深克隆 复制里面的子节点 false 浅克隆
添加到ul 最后面appendChild
-图片播放的同时,下面小圆圈模块跟随一起变化
最简单的做法是再声明一个变量circle ,每次点击自增一,注意:左侧按钮也需要这个变量,因此声明全局变量
因为前面把第一张图片克隆了,因此小圆圈比图片少一个,要加一个判断条件:if circle = 图片数量-1 说明走到了克隆的图片了 此时让circle = 0 复原回去
自动播放
添加一个定时器
自动播放轮播图,实际就类似于点击了右按钮
此时我们使用手动调用右侧按钮点击事件 arrow_r.click()
鼠标经过focus 就停止定时器
节流阀
用于防止轮播图连续点击造成播放过快
节流阀目的:当上一个函数动画执行完毕,再去执行下一个函数动画,让事件无法连续触发
核心思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
开始设置一个变量 var flag = true;
if (flag){flag=flase;do something;} 关闭水龙头
利用回调函数,动画执行完毕,flag = true 打开水龙头
(os:但是我下面的代码不知道为什么实现不了节流阀功能,就没加进去,如果有大佬看到了知道怎么改请指教一下)
如果加上节流阀,布局应该是下面的样式:
var flag = true; //节流阀
arrow_r.addEventListener("click", function () {
if (flag) {
flag = false;
//如果走到了最后复制的一张 ul 要快速复原 left 改为0
.........
animate(ul, -num * focusWidth, function () {
flag = true; //打开节流阀
});
.........
}
});
arrow_l.addEventListener("click", function () {
if (flag) {
flag = false;
//如果走到了最后复制的一张 ul 要快速复原 left 改为0
...........
animate(ul, -(num * focusWidth), function () {
flag = true;
});
...........
}
});
代码:
HTML 代码:
<!-- 引入首页的css文件 -->
<link rel="stylesheet" href="css/index.css" />
<!-- 引入JS文件 -->
<script src="js/animate.js"></script>
<!--这个JS文件必须写到 index.js 上面-->
<script src="js/index.js"></script>
</head>
<body>
<div class="focus fl">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow_l"> < </a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow_r"> > </a>
<!-- 必须用ul布局 轮播图效果核心的滚动区域 -->
<!-- 有几个li 轮播图内就有几个图片 -->
<ul>
<li>
<a href="#"><img src="upload/focus1.jpg" /></a>
</li>
<li>
<a href="#"><img src="upload/focus2.jpg" /></a>
</li>
<li>
<a href="#"><img src="upload/focus3.jpg" /></a>
</li>
<li>
<a href="#"><img src="upload/focus4.jpg" /></a>
</li>
</ul>
<!-- 小圆圈 -->
<ol class="circle"></ol>
</div>
CSS代码:
.fl {
float: left;
}
.focus {
position: relative;
height: 440px;
width: 721px;
background-color: purple;
overflow: hidden;
}
.focus ul {
position: absolute; /*加上定位才可以使用动画*/
top: 0;
left: 0;
width: 600%; /*设为父盒子宽度的600% 确保轮播图的四个图片有足够宽的位置浮动起来*/
}
.focus ul img {
width: 720px;
height: 440px;
float: left;
}
.arrow_l,
.arrow_r {
display: none; /*为了轮播图效果先隐藏按钮*/
position: absolute;
top: 50%; /* 走父亲高度的一半 */
transform: translateY(-50%); /* 走的自己高度的一半 */
width: 24px;
height: 40px;
background: rgba(0, 0, 0, 0.3);
font-family: "icomoon";
font-size: 18px;
text-align: center;
line-height: 40px;
color: #fff;
z-index: 2; /*添加层级,让它在ul里面显示出来*/
}
.arrow_r {
right: 0;
}
.circle {
position: absolute;
bottom: 10px;
left: 50px;
}
.circle li {
float: left;
width: 8px;
height: 8px;
/* background-color: #fff; */
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
border-radius: 50%;
/* 鼠标经过显示小手 */
cursor: pointer;
}
.current {
background-color: #fff;
}
JS 代码:
window.addEventListener("load", function () {
//预加载
//1.获取元素
var arrow_l = document.querySelector(".arrow_l");
var arrow_r = document.querySelector(".arrow_r");
var focus = document.querySelector(".focus");
var focusWidth = focus.offsetWidth; //获取图片宽度
//2.鼠标经过轮播图区域 左右按钮显示
focus.addEventListener("mouseenter", function () {
arrow_l.style.display = "block";
arrow_r.style.display = "block";
//停止定时器,停止自动播放
clearInterval(timer);
timer = null; //清除定时器变量
});
//鼠标离开轮播图区域 左右按钮隐藏
focus.addEventListener("mouseleave", function () {
arrow_l.style.display = "none";
arrow_r.style.display = "none";
//开启定时器,自动播放开始
timer = setInterval(function () {
//手动调用点击事件
arrow_r.click();
}, 2000);
});
//3.动态生成小圆圈 里面有几张图片 就创建几个小圆点
var ul = focus.querySelector("ul");
var ol = focus.querySelector(".circle");
for (var i = 0; i < ul.children.length; i++) {
//创建一个li
var li = document.createElement("li");
//记录当前小圆圈的索引号 通过自定义属性来做
li.setAttribute("index", i);
//把li插入ol里面
ol.appendChild(li);
//4.小圆圈的排他事件 可以在生成小圆圈的同时直接绑定事件
// 点击当前小圆圈,就添加current 类,其余的就移除这个类
li.addEventListener("click", function () {
//(1)干掉所有人 所有li 清除 current 类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
//(2)留下自己 自己添加 current 类名
this.className = "current";
//5.点击小圆圈,移动图片 移动的是ul
//ul移动距离:小圆圈的索引号乘以图片的宽度(是负值)
//点击了小圆圈,就拿到当前li的索引号
var index = this.getAttribute("index");
//当点击了某个li 就把这个li的索引号给 num
num = index;
//当点击了某个li 就把这个li的索引号给 circle
circle = index;
animate(ul, -(index * focusWidth));
});
}
//第一个ol小圆圈添加类名 current
ol.children[0].className = "current";
//6.克隆第一张图片 放到最后面
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
//7.点击右侧按钮,图片滚动一张
var num = 0;
var circle = 0; //控制小圆圈的播放
//var flag = true; //节流阀
arrow_r.addEventListener("click", function () {
//如果走到了最后复制的一张 ul 要快速复原 left 改为0
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth);
//8.点击右侧按钮,小圆圈跟着一起变化,可以再声明一个变量控制小圆圈的播放
//如果circle = 4 ,即走到最后了,复原
circle++;
if (circle == ol.children.length) {
circle = 0;
}
circleChange(); //调用函数
});
//9.点击左侧按钮,图片滚动一张
arrow_l.addEventListener("click", function () {
//如果走到了最后复制的一张 ul 要快速复原 left 改为0
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * focusWidth + "px";
}
num--;
animate(ul, -(num * focusWidth));
//点击左侧按钮,小圆圈跟着一起变化,可以再声明一个变量控制小圆圈的播放
circle--;
//如果 circle < 0 说明是第一张图片 此时小圆圈要改为第四个小圆圈(3)
if (circle < 0) {
circle = ol.children.length - 1;
}
circleChange(); //调用函数
});
function circleChange() {
//先清除其余小圆圈类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
//留下当前小圆圈的 current 类名
ol.children[circle].className = "current";
}
//10.自动播放功能
var timer = setInterval(function () {
//手动调用点击事件
arrow_r.click();
}, 2000);
});