1.本质:两个定时器A,B
在A执行之后B执行,B执行完之后A执行,B必须在下一次A执行的时候完成
2.定时器A 假设3000ms启动一次
定时器B 1ms启动一次
A启动后,启动定时器B,B达到临界条件关闭,下一次A再次启动,B就被开启,达到临界条件关闭,实现自动轮播效果
轮播图可拆分为 两个小效果
- 自动轮播
- 点到哪里,移动到那里,再继续轮播
结构
先实现自动轮播效果
- ul2 包含图片,宽度为单个图片宽度,设置为overflow hidden
- ul 下的li 第一个和最后一个相同,实现无缝首尾切换
分析
变量 | index |
---|---|
因变量1 | ul2的left值 |
因变量2 | a标签的样式 |
这两个变量是在index发生变化变化之后先后变化还是同时变化
根据轮播图的效果来看,是ul2 left 变化之后再 a的样式变化
初始状态 index = 0,图片在第[0]张,a为0
下一个状态 index = 1 ,图片在第[1]张,a为1
下一个状态 index = 2 ,图片在第[2]张,a为2
下一个状态 index = 3 ,图片在第[3]张,a为3
下一个状态 index = 4 ,图片在第[4]张,a为4[已经到边界]
下一个状态 index = 5 [已经到边界],图片在第?张,a为?
此时已经到最后一张图片,该怎么办?
移动到最后一张图片,瞬间切换到第一张图片[0],a修改为0
再次强调,ul2 left先改变,a之后才改变,但是此时图片已经移动过,如何瞬间切换到第一张图片?在a切换的事件中可以操作。
总体思路
初始状态 index = 0,图片在第[0]张,a为0
下一个状态 index = 1 ,图片在第[1]张,a为1
下一个状态 index = 2 ,图片在第[2]张,a为2
下一个状态 index = 3 ,图片在第[3]张,a为3
下一个状态 index = 4 ,图片在第[4]张,a为4[已经到边界]
下一个状态 index = 5 [已经到边界],图片在第5张,[index = 0,a为0,同时,图片切换到[0],也就是ul2 left 值为0px]
index = 0;
auto();
function auto() {
clearInterval(time_auto);
var time_auto = setInterval(function() {
index++; //定时器执行一次,index增加一次
if (index == img.length) { // 上一句的index++ 达到6 也就是index = 5时,此时归0
index = 0;
}
move(ul2, "left", -img_width * index, 10, function() {
setA();
});
}, 3000);
}
分析move函数细节
var timer_move;
function move(ele,attr,target,speed,callback){
clearInterval(timer_move);//清除定时器
var current = getStyleParsedInt(ele,attr);//获取初始left
//这句话不能放到定时器里面,不然会每执行一次,获取一次当前的left,因为一开始left为0
//target -600 ,所以speed = - speed ,但是下一次还是会执行这句话,所以不能写到定时器里面
if(current > target)//在目标右侧,就减【左移】,在目标左侧,就加【右移】
{
speed = - speed;//写在定时器里面,看不到变化,其实1ms有10px的变化
}
//上面已经确定好ele移动的方向
//下面确认边界条件即可
//什么时候停止定时器
timer_move = setInterval(function(){
var oldValue = getStyleParsedInt(ele,attr);
var newValue = oldValue + speed;
ele.style[attr] = newValue + "px" ;
if(speed<0 && newValue <= target || speed > 0 && newValue >= target)
{
clearInterval(timer_move);
callback();
}
},1);
}
什么时候停止定时器B,target = = 当前left
if (target == newValue) {
clearInterval(timer_move);
callback();
}
这句即可满足我们自动轮播的要求,但是如果speed更改,newValue始终不等于target,怎么办?
if(speed<0 && newValue <= target || speed > 0 && newValue >= target)
{
clearInterval(timer_move);
callback();
}
此时的边界条件就是:初始current>target ==>speed<0 ,但是 newValue <= target,停止,此时原来大于target的ele跑到target左边了,或者等于target;同理,小于target的ele跑到target右侧或者等于target,也是达到临界条件。
分析setA函数
function setA() {
if (index == aList.length) {//在这里,也就是上面分析的index = 5 的状态
index = 0;
ul2.style.left = 0 + "px";
}
for (var i = 0; i < aList.length; i++) {
aList[i].style.backgroundColor = ""; //回复默认样式
}
aList[index].style.backgroundColor = "red";
}
了解到上面的分析,再写轮播图,就不会遇到太多障碍了
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="../../css/diy-default.css">
<link rel="stylesheet" href="../../css/resetm.css">
<style>
.ul1 li {
text-align: center;
list-style: none;
line-height: 50px;
margin-left: 5px;
margin-right: 5px;
float: left;
}
.ul2 {
width: 3600px;
height: 600px;
position: absolute;
overflow: hidden;
}
.ul2 li {
width: 600px;
height: 600px;
/* line-height: 536px; */
float: left;
text-align: center;
list-style: none;
}
.ul2 li img {
width: 600px;
height: 600px;
}
.box {
position: relative;
width: 600px;
margin: 100px auto;
height: 600px;
overflow: hidden;
}
.ul1 {
position: absolute;
bottom: 0;
/* margin: 0 auto; */
width: 250px;
height: 40px;
left: 50%;
transform: translateX(-50%);
opacity: 0.7;
}
.ul1 a{
float:left;
width: 40px;
height: 40px;
border-radius: 50%;
background:black;
}
a:hover{
background-color: red;
}
</style>
</head>
<body>
<div class="box cl">
<ul class="ul2 cl">
<li><img src="img/1b49f153650d9d22daa8c9a3f81648d0.jpeg" alt=""></li>
<li><img src="img/2b0dfbf79d4acb2c510d79969cfd61da.jpg" alt=""></li>
<li><img src="img/4a13728ae8448bde09e26edd1780bec1.jpg" alt=""></li>
<li><img src="img/5cbd148adbb3dbbc8253c91f4064167e.jpeg" alt=""></li>
<li><img src="img/98c6a0f91814b8c5cc8b50408cdf75ec.jpg" alt=""></li>
<li><img src="img/1b49f153650d9d22daa8c9a3f81648d0.jpeg" alt=""></li>
</ul>
<ul class="ul1 cl cen">
<li><a href="javascript:0"></a></li>
<li><a href="javascript:0"></a></li>
<li><a href="javascript:0"></a></li>
<li><a href="javascript:0"></a></li>
<li><a href="javascript:0"></a></li>
</ul>
</div>
</body>
<script type="text/javascript" src="../../js/jx.js">
</script>
<script>
var box = document.querySelector(".box");
var ul1 = document.querySelector(".ul1");
var ul2 = document.querySelector(".ul2");
var ul1_li = document.querySelectorAll(".ul1 li");
var ul2_li = document.querySelectorAll(".ul2 li");
var img = document.querySelectorAll("img");
var aList = document.querySelectorAll(".ul1 a");
// console.log(img[0]);
var img_width = getStyleParsedInt(img[0], "width");
// var step = 1;
var index = 0;
console.log(img_width);
aList[index].style.backgroundColor = "red";
var time_auto;
auto();
function auto() {
clearInterval(time_auto);
var time_auto = setInterval(function() {
index++; //
if (index == img.length) { //
index = 0;
// ul2.style.left = 0 + "px";
}
move(ul2, "left", -img_width * index, 10, function() {
setA();
}); //index == 5
if (index == 5) {
console.log(getStyleParsedInt(ul2, "left"));
//-2140
}
}, 3000);
}
for (let i = 0; i < aList.length; i++) { //for先执行完,再执行onclick
// aList[i].num = i;
aList[i].onclick = function() {
//关闭自动切换时的定时器
clearInterval(time_auto);
// index = this.num;
index = i;
setA();
move(ul2, "left", -img_width * i, 10, function() {
// auto();
});
}
}
function setA() { //alist 0 1 2 3 imgList 0 1 2 3 4
// if(index == (imgList.length - 1)){
if (index == aList.length) {
// alert("xxx");
index = 0;
ul2.style.left = 0 + "px";
}
for (var i = 0; i < aList.length; i++) {
aList[i].style.backgroundColor = ""; //回复默认样式
}
aList[index].style.backgroundColor = "red";
}
</script>
</html>