webAPI案例之十分钟搞懂js原生轮播
webAPI案例之十分钟搞懂js原生轮播
一般轮播图的功能需求:
1.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。
2.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。
3.图片播放的同时,下面小圆圈模块跟随一起变化。
4.点击小圆圈,可以播放相应图片。
5.鼠标不经过轮播图,轮播图也会自动播放图片。鼠标经过,轮播图模块, 自动播放停止。
虽然bootstrap等对此的封装非常好,但是我们要记住。原生的东西才能帮助我们进步。那些封装仅仅是方便了我们开发。如果不注重原生,就好比你走路走不利索时,别人给了你一个电动轮椅。让你移动的非常之快,但不是你的东西终究还是不属于你。有一天别人把你的轮椅拿走了你怎么办。你难道还不靠自己的双腿而是再去找工具吗。
1.开始
要实现功能搭建结构样式和实现需求1
首先需要知道轮播图的构造结构,主要是一个ul里面放几个小li,li再浮动到一行。li里面放上轮播显示的图片。要明白做移动的是ul
这里我先使ul里面的小li全部显示
本步骤相关代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
position: relative;
width: 400px;
height: 200px;
border: 1px solid red;
margin: 100px auto;
}
ul {
width: 1600px;
}
li {
float: left;
width: 400px;
height: 200px;
list-style: none;
}
img {
width: 400px;
height: 200px;
}
a {
display: none;
position: absolute;
width: 20px;
height: 30px;
font-size: 20px;
color: #000;
text-align: center;
text-decoration: none;
background-color: darkorange;
opacity: .3;
left: 0;
top: 50%;
transform: translateY(-50%);
}
.right {
left: 380px;
}
</style>
</head>
<body>
<!-- 轮播图开始 -->
<div class="carousel">
<!-- 左右符号 -->
<a class="left" href="javascript:;"> <</a>
<a class="right" href="javascript:;"> ></a>
<ul>
<li><img src="img/01.jpg" alt=""></li>
<li><img src="img/02.jpg" alt=""></li>
<li><img src="img/03.jpg" alt=""></li>
<li><img src="img/04.jpg" alt=""></li>
</ul>
</div>
<script>
var div = document.querySelector("div");
var a = document.querySelectorAll("a");
div.addEventListener("mouseover", function() {
a[0].style.display = "block";
a[1].style.display = "block";
});
div.addEventListener("mouseout", function() {
a[0].style.display = "none";
a[1].style.display = "none";
});
</script>
</body>
</html>
2. 现在让我实现按钮的功能吧
要实现功能点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。
右面按钮效果:
左面按钮效果:
思路相关:(这里的运到是借助我一回总结的动画封装相信聪明的你没有忘记)
右面按钮:
每次点击一下右边按钮,ul向左移动一个小li的宽度。这里可以借助一个计数变量i,i开始可先设为0,(注意我i自增的顺序喔这里我是先自增再加的1 。当然随你习惯吧我也只是根据我的思路来的)动画函数的target值便是-400 * i
调完运到函数再自增一。
什么时候结束呢毕竟这里我们只是显示4张图,我们的要求是到了最后一张再点击又回到了第一张。这里我们需要多准备一个小li放到最后。把第一个小li的内容在放这里面一份。如这样
我们要做的操作流程:
可以看到我们的重点是放在最后一个小li的时候,ul要进行怎样的操作
即它运动的第五的小li的时候我们要ul的left值设置为0
相关代码:
a[1].addEventListener("click", function() {
if (i == 4) {
ul.style.left = 0;
i = 0;
}
i++;
go(ul, -400 * i);
});
显示第五个小li的时候,它的left值为-400*4
我们的思路要放在从第5个小li到第2个小li(实际显示效果即最后一张到第一张)的时候的操作
左面按钮
原理与上面相同,这里我只介绍从第一个小li到最后一个小li(实际上的第一张到最后一张)
我们要做的操作流程:
这里的重点思路上从一个小li到最后一个小li的操作。开始值i仍然为0 。不过这里是用i–,且我把i–放到了前面 。因为我习惯是负数判断
a[0].addEventListener("click", function() {
i--;
if (i < 0) {
ul.style.left = -400 * 4 + "px";
i = 3;
}
go(ul, -400 * i);
});
即一点击,事件触发。i变成成了负数。这里我们需要迅速把ul的left值变成-400*4
即从第一张迅速到了最后一张,还是因为第一张和最后一张的内容相同。所以在效果上我们是看不出变化的了。重新设置i
这一事件触发的除了要进行上面操作,还要用动画将li显示到第四张,第四张的left即-3*400 。3即为上面i的重设值。
下面要显示的就每次触发i–就ok了
本步源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
position: relative;
width: 400px;
height: 200px;
border: 1px solid red;
margin: 100px auto;
overflow: hidden;
}
ul {
position: absolute;
width: 2000px;
}
li {
float: left;
width: 400px;
height: 200px;
list-style: none;
}
img {
width: 400px;
height: 200px;
}
a {
display: none;
position: absolute;
width: 20px;
height: 30px;
font-size: 20px;
color: #000;
text-align: center;
text-decoration: none;
background-color: darkorange;
opacity: .3;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: 100;
}
.right {
left: 380px;
}
</style>
</head>
<body>
<!-- 轮播图开始 -->
<div class="carousel">
<!-- 左右符号 -->
<a class="left" href="javascript:;"> <</a>
<a class="right" href="javascript:;"> ></a>
<ul>
<li><img src="img/01.jpg" alt=""></li>
<li><img src="img/02.jpg" alt=""></li>
<li><img src="img/03.jpg" alt=""></li>
<li><img src="img/04.jpg" alt=""></li>
<li><img src="img/01.jpg" alt=""></li>
</ul>
</div>
<script>
var div = document.querySelector("div");
var ul = document.querySelector("ul");
var a = document.querySelectorAll("a");
div.addEventListener("mouseover", function() {
a[0].style.display = "block";
a[1].style.display = "block";
});
div.addEventListener("mouseout", function() {
a[0].style.display = "none";
a[1].style.display = "none";
});
// 按钮功能,右面
var i = 0
a[1].addEventListener("click", function() {
if (i == 4) {
ul.style.left = 0;
i = 0;
}
i++;
go(ul, -400 * i);
});
// 左面同理
a[0].addEventListener("click", function() {
i--;
if (i < 0) {
ul.style.left = -400 * 4 + "px";
i = 3;
}
go(ul, -400 * i);
});
function go(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
obj.style.left = obj.offsetLeft + step + "px";
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
}, 20)
}
</script>
</body>
</html>
3. 按钮与小圆圈建立联系
要实现功能图片播放的同时,下面小圆圈模块跟随一起变化。
看效果:
一般的小圆圈是用小li做的,我做的时候拿的span。。。我是div套的span。然后给div用的flex布局。只怪我一开始想偏了哈哈
思路相关:(我这里做了一些修改主要是变量名字,也无所谓)
这里控制小圆点无非是设置了个全局变量k,往右走k++,往左k–。然后做一下端点判断。比如k++的,到了3(从0开始,3就是最后一个了)下一个应该重新设置为0了。故加入一个判断if(k>3){k=0}
就ok。另一个放下同理
本步骤代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
position: relative;
width: 400px;
height: 200px;
margin: 100px auto;
overflow: hidden;
}
ul {
position: absolute;
width: 2000px;
}
li {
float: left;
width: 400px;
height: 200px;
list-style: none;
}
img {
width: 400px;
height: 200px;
}
a {
display: none;
position: absolute;
width: 20px;
height: 30px;
font-size: 20px;
color: #000;
text-align: center;
text-decoration: none;
background-color: darkorange;
opacity: .3;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: 100;
}
.right {
left: 380px;
}
/* 小圆点 */
.carousel .dot {
display: flex;
justify-content: space-around;
position: absolute;
width: 200px;
height: 15px;
left: 50%;
transform: translateX(-50%);
top: 75px
}
.dot span {
margin-left: 5px;
margin-right: 5px;
width: 20px;
height: 15px;
font-size: 12px;
text-align: center;
line-height: 15px;
border-radius: 50%;
opacity: .5;
background-color: yellowgreen;
cursor: pointer;
}
.dot .selected {
opacity: 1;
}
</style>
</head>
<body>
<!-- 轮播图开始 -->
<div class="carousel">
<!-- 左右符号 -->
<a class="left" href="javascript:;"> <</a>
<a class="right" href="javascript:;"> ></a>
<ul>
<li><img src="img/01.jpg" alt=""></li>
<li><img src="img/02.jpg" alt=""></li>
<li><img src="img/03.jpg" alt=""></li>
<li><img src="img/04.jpg" alt=""></li>
<li><img src="img/01.jpg" alt=""></li>
</ul>
<div class="dot">
</div>
</div>
<script>
var div = document.querySelector("div");
var ul = document.querySelector("ul");
var a = document.querySelectorAll("a");
var dot = document.querySelector(".dot");
// 创建小圆点
for (var i = 0; i < ul.children.length - 1; i++) {
var newSpan = document.createElement("span");
newSpan.innerHTML = i + 1;
newSpan.setAttribute("data-index", i);
dot.appendChild(newSpan);
}
// 给第一个圆圈设置默认样式
var span = dot.children;
span[0].className = "selected";
// 显示左右按钮
div.addEventListener("mouseover", function() {
a[0].style.display = "block";
a[1].style.display = "block";
});
div.addEventListener("mouseout", function() {
a[0].style.display = "none";
a[1].style.display = "none";
});
// 按钮功能,右面
var tab = 0;
var k = 0;
a[1].addEventListener("click", function() {
if (tab == 4) {
ul.style.left = 0;
tab = 0;
}
k++;
tab++;
console.log(tab);
go(ul, -400 * tab);
// 控制小圆点类名
if (k > 3) {
k = 0;
}
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
});
// 左面同理
a[0].addEventListener("click", function() {
if (tab == 0) {
ul.style.left = -400 * 4 + "px";
tab = 4;
}
tab--;
k--;
go(ul, -400 * tab);
if (k < 0) {
k = 3
}
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
});
function go(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
obj.style.left = obj.offsetLeft + step + "px";
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
}, 20)
}
</script>
</body>
</html>
4. 开始添加小圆圈的功能按键咯
需求:点击小圆圈,可以播放相应图片。
效果图:
思路相关:
这里我先给小圆圈们分别设置一个自定义属性。像这样
可能上一步你也看到了,我这里的小圆圈均是使用节点创建元素来的。所以我们在该元素的创建时便给它设置上这个属性
相关代码:
// 创建小圆点
for (var i = 0; i < ul.children.length - 1; i++) {
var newSpan = document.createElement("span");
newSpan.innerHTML = i + 1;
newSpan.setAttribute("data-index", i);
dot.appendChild(newSpan);
}
接下便是给小圆点分别绑定事件了
相关代码:
值得注意的上全局变量k是记录小圆点是否选中的值,全局变量tab是记录给动画函数传参的target值。
问为啥要记录呢
很简单。
- 1 如果你选中第三个小圆点,那么首先ul要做动画使其运动到第三个小li的显示位置。并且该圆点的状态要变成选中状态
- 2 你又按了一下右面的按钮,即你想让他从上一个的第三张跑到第四张。试问你没有一个记录值做记录。按钮的那个函数怎么知道要往哪走呢。
- 3 所以用一个全局变量使它们共享。即1中已经把当前的target和k的值记录下来了,按钮函数调用这个变量的值即可
// 给小圆点添加事件
for (var i = 0; i < span.length; i++) {
span[i].addEventListener("click", function() {
tab = k = this.getAttribute("data-index");
go(ul, -tab * 400);
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
})
}
本步骤完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
position: relative;
width: 400px;
height: 200px;
margin: 100px auto;
overflow: hidden;
}
ul {
position: absolute;
width: 2000px;
}
li {
float: left;
width: 400px;
height: 200px;
list-style: none;
}
img {
width: 400px;
height: 200px;
}
a {
display: none;
position: absolute;
width: 20px;
height: 30px;
font-size: 20px;
color: #000;
text-align: center;
text-decoration: none;
background-color: darkorange;
opacity: .3;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: 100;
}
.right {
left: 380px;
}
/* 小圆点 */
.carousel .dot {
display: flex;
justify-content: space-around;
position: absolute;
width: 200px;
height: 15px;
left: 50%;
transform: translateX(-50%);
top: 75px
}
.dot span {
margin-left: 5px;
margin-right: 5px;
width: 20px;
height: 15px;
font-size: 12px;
text-align: center;
line-height: 15px;
border-radius: 50%;
opacity: .5;
background-color: yellowgreen;
cursor: pointer;
}
.dot .selected {
opacity: 1;
}
</style>
</head>
<body>
<!-- 轮播图开始 -->
<div class="carousel">
<!-- 左右符号 -->
<a class="left" href="javascript:;"> <</a>
<a class="right" href="javascript:;"> ></a>
<ul>
<li><img src="img/01.jpg" alt=""></li>
<li><img src="img/02.jpg" alt=""></li>
<li><img src="img/03.jpg" alt=""></li>
<li><img src="img/04.jpg" alt=""></li>
<li><img src="img/01.jpg" alt=""></li>
</ul>
<div class="dot">
</div>
</div>
<script>
var div = document.querySelector("div");
var ul = document.querySelector("ul");
var a = document.querySelectorAll("a");
var dot = document.querySelector(".dot");
// 创建小圆点
for (var i = 0; i < ul.children.length - 1; i++) {
var newSpan = document.createElement("span");
newSpan.innerHTML = i + 1;
newSpan.setAttribute("data-index", i);
dot.appendChild(newSpan);
}
// 给第一个圆圈设置默认样式
var span = dot.children;
span[0].className = "selected";
// 显示左右按钮
div.addEventListener("mouseover", function() {
a[0].style.display = "block";
a[1].style.display = "block";
});
div.addEventListener("mouseout", function() {
a[0].style.display = "none";
a[1].style.display = "none";
});
// 按钮功能,右面
var tab = 0;
var k = 0;
a[1].addEventListener("click", function() {
if (tab == 4) {
ul.style.left = 0;
tab = 0;
}
k++;
tab++;
console.log(tab);
go(ul, -400 * tab);
// 控制小圆点类名
if (k > 3) {
k = 0;
}
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
});
// 左面同理
a[0].addEventListener("click", function() {
if (tab == 0) {
ul.style.left = -400 * 4 + "px";
tab = 4;
}
tab--;
k--;
go(ul, -400 * tab);
if (k < 0) {
k = 3
}
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
});
// 给小圆点添加事件
for (var i = 0; i < span.length; i++) {
span[i].addEventListener("click", function() {
tab = k = this.getAttribute("data-index");
go(ul, -tab * 400);
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
})
}
function go(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
obj.style.left = obj.offsetLeft + step + "px";
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
}, 20)
}
</script>
</body>
</html>
5 终于接近尾声了(以简单开始以简单结束)
鼠标不经过轮播图,轮播图也会自动播放图片。鼠标经过,轮播图模块, 自动播放停止。
效果:
**核心代码:**即用定时1s点一次右面按钮。同时鼠标移入去除鼠标移出再开始
// 自动播放
var timer = setInterval(function() {
a[1].click();
}, 1000);
6. 全部代码
加上节流阀:即使你快速的点击两边按钮,图片的移动速度也不会随着你点击速度加快而加快。
利用我们自己封装的动画函数里的回调函数。
回调函数的执行,是在当前动画做完之后才开始
demo
var falg=true;
a[0].addEventListener("click", function() {
if(falg==ture){
flag=false;
我们要做的事情
调用动画函数
go(obj,target,function(){//即在动画之后才会再把falg改为ture,在动画未执行完之前,falg一直是false。该点击事件中要做的事情不会再来执行。就直接卡死在第一句判断了
flag=ture;
});
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
position: relative;
width: 400px;
height: 200px;
margin: 100px auto;
overflow: hidden;
}
ul {
position: absolute;
width: 2000px;
}
li {
float: left;
width: 400px;
height: 200px;
list-style: none;
}
img {
width: 400px;
height: 200px;
}
a {
display: none;
position: absolute;
width: 20px;
height: 30px;
font-size: 20px;
color: #000;
text-align: center;
text-decoration: none;
background-color: darkorange;
opacity: .3;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: 100;
}
.right {
left: 380px;
}
/* 小圆点 */
.carousel .dot {
display: flex;
justify-content: space-around;
position: absolute;
width: 200px;
height: 15px;
left: 50%;
transform: translateX(-50%);
top: 75px
}
.dot span {
margin-left: 5px;
margin-right: 5px;
width: 20px;
height: 15px;
font-size: 12px;
text-align: center;
line-height: 15px;
border-radius: 50%;
opacity: .5;
background-color: yellowgreen;
cursor: pointer;
}
.dot .selected {
opacity: 1;
}
</style>
</head>
<body>
<!-- 轮播图开始 -->
<div class="carousel">
<!-- 左右符号 -->
<a class="left" href="javascript:;"> <</a>
<a class="right" href="javascript:;"> ></a>
<ul>
<li><img src="img/01.jpg" alt=""></li>
<li><img src="img/02.jpg" alt=""></li>
<li><img src="img/03.jpg" alt=""></li>
<li><img src="img/04.jpg" alt=""></li>
<li><img src="img/01.jpg" alt=""></li>
</ul>
<div class="dot">
</div>
</div>
<script>
var div = document.querySelector("div");
var ul = document.querySelector("ul");
var a = document.querySelectorAll("a");
var dot = document.querySelector(".dot");
// 创建小圆点
for (var i = 0; i < ul.children.length - 1; i++) {
var newSpan = document.createElement("span");
newSpan.innerHTML = i + 1;
newSpan.setAttribute("data-index", i);
dot.appendChild(newSpan);
}
// 给第一个圆圈设置默认样式
var span = dot.children;
var timer = null;
span[0].className = "selected";
// 显示左右按钮
div.addEventListener("mouseover", function() {
a[0].style.display = "block";
a[1].style.display = "block";
clearInterval(timer);
});
div.addEventListener("mouseout", function() {
a[0].style.display = "none";
a[1].style.display = "none";
// 自动播放
timer = setInterval(function() {
a[1].click();
}, 1000);
});
// 按钮功能,右面
var tab = 0;
var k = 0;
var flag = true;
a[1].addEventListener("click", function() {
if (flag) {
flag = false;
console.log(flag);
if (tab == 4) {
ul.style.left = 0;
tab = 0;
}
k++;
tab++;
go(ul, -400 * tab, function() {
flag = true;
});
// 控制小圆点类名
if (k > 3) {
k = 0;
}
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
}
});
// 左面同理
a[0].addEventListener("click", function() {
if (flag) {
flag = false;
if (tab == 0) {
ul.style.left = -400 * 4 + "px";
tab = 4;
}
tab--;
k--;
go(ul, -400 * tab, function() {
flag = true;
});
if (k < 0) {
k = 3
}
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
}
});
// 给小圆点添加事件
for (var i = 0; i < span.length; i++) {
span[i].addEventListener("click", function() {
tab = k = this.getAttribute("data-index");
go(ul, -tab * 400);
for (var j = 0; j < span.length; j++) {
span[j].className = "";
}
span[k].className = "selected";
})
}
// 自动播放
var timer = setInterval(function() {
a[1].click();
}, 1000);
function go(obj, target, fn) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
obj.style.left = obj.offsetLeft + step + "px";
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
fn && fn();
}
}, 20)
}
</script>
</body>
</html>
上一篇: Spring 数据库事务管理
推荐阅读