学习了许多的javascript知识,我们今天来做一个应用—轮播图。许多网站上都有轮播图,像淘宝,京东等电商网站的首页,轮播图总是不可获取的页面组成元素。往往大家都是上网找插件(最出名的可能是swiper)。假如自己动手让你用原生js写一个呢?
下面我们开始今天的主题,一个可自动轮播+点击轮播+无缝滚动的原生轮播图。
上代码:
css部分
// 样式重置
* {
margin: 0;
padding: 0;
list-style: none;
}
// 主要样式
// 大盒子
.box{
width: 560px;
height: 300px;
position: relative;
overflow: hidden;
border: 1px solid #f00;
margin: 30px auto;
box-shadow: 1px 1px 10px 5px blue;
}
// 包裹图片的盒子,这样做是为了无缝滚动服务
.wrap{
position: relative;
width: 5000px;
height: 300px;
top: 0;
left: 0px;
}
// 图片盒子
.wrap ul{
position: absolute;
top: 0;
left: 0;
}
.wrap ul li{
float: left;
}
// 控制圆点盒子
.control{
position: absolute;
bottom: 5px;
right: 0;
}
// 控制圆点设置
.control li{
margin-right: 5px;
width: 20px;
height: 20px;
line-height: 20px;
font-weight: bold;
text-align: center;
background: #fff;
cursor: pointer;
border-radius: 50%;
float: left;
}
// 选中状态
.control li.active{
background: red;
color: #fff;
}
// 按钮盒子
.btn{
position: absolute;
width: 100%;
top: 50%;
margin-top: -25px;
}
// 按钮样式
.btn a{
width: 50px;
height: 50px;
line-height: 45px;
text-decoration-line: none;
color: aliceblue;
font-size: 36px;
background: rgba(0, 0, 0, .5);
text-align: center;
border-radius: 50%;
opacity: .5;
display: none;
}
.btn .prev{
float: left;
}
.btn .next{
float: right;
}
// 滑入选中状态
.btn .prev:hover,
.btn .next:hover {
filter: alpha(opacity=100);
opacity: 1;
}
css部分需要注意的是我们要做无缝滚动的效果所以我们的大盒子 wrap 要宽度足够才能让每一张图片排成一排,因为我们始终动的只是包裹图片的 ul。
接下来是html:
<div class="box" id="wrap">
<div class="wrap" >
<ul id="imgBox"></ul>
</div>
<ul class="control" id="control"></ul>
<div class="btn">
<a href="javascript:;" class="prev"><</a>
<a href="javascript:;" class="next">></a>
</div>
</div>
布局这方面没啥说的,因为是动态生成图片和控制圆点,所以没有直接写 li。
下面主要的来了
js部分:
// 元素获取
var wrap = document.getElementById("wrap")
var imgBox = document.getElementById("imgBox");
var control = document.getElementById("control");
var prev = document.getElementsByTagName("a")[0];
var next = document.getElementsByTagName("a")[1];
var imgWidth = 560;
var target = 0;
var imgIndex = 0;
var timer = null;
var autoTimer = null;
// ------------------------start--------------------
var imgs = [
'img/0.jpg',
'img/1.jpg',
'img/2.jpg',
'img/3.jpg',
'img/4.jpg'
]
var lis = []; // 图片列表数组
var ctrs = [];// 控制点数组
// 动态创建图片列表
for (let index = 0; index < imgs.length; index++) {
lis.push('<li><img src="'+imgs[index]+'" /></li>')
ctrs.push('<li>'+(index-1+2)+'</li>')
}
// 加入到页面中
imgBox.innerHTML = lis.join("");
// 复制节点
imgBox.appendChild(imgBox.children[0].cloneNode(true));
control.innerHTML = ctrs.join("");
control.children[0].setAttribute("class","active");
//---------------------------------------------------
//按钮显示隐藏
wrap.onmouseover = function () {
prev.style.display = "block";
next.style.display = "block";
clearInterval(autoTimer);// 清除自动轮播
}
wrap.onmouseout = function () {
prev.style.display = "none";
next.style.display = "none";
autoPlay();// 开启自动轮播
}
// 控制点循环绑定事件
var ctrlis = control.getElementsByTagName("li");
for (let i = 0; i < ctrlis.length; i++) {
ctrlis[i].index = i;// 记录元素
ctrlis[i].onmouseover = function(){
// clearInterval(timer);
imgIndex = this.index;
animate(imgIndex);
}
}
// 上一页
prev.onclick = function(){
clearInterval(timer);// 清除运动定时器
imgIndex--;
if (imgIndex == -1) {
imgBox.style.left = -imgWidth*(imgBox.children.length-1) + "px";
imgIndex = imgBox.children.length-2;
}
animate(imgIndex);
}
// 下一页
next.onclick = function(){
clearInterval(timer);
imgIndex++;
if (imgIndex == imgBox.children.length) {
imgBox.style.left = 0;
imgIndex = 1;
}
animate(imgIndex);
}
// 运动封装
function animate(index){
clearInterval(timer);
// 控制点样式修改
for(let i = 0; i < ctrlis.length; i++){
ctrlis[i].className = "";
}
ctrlis[index%ctrlis.length].className="active"
//开启定时器
timer = setInterval(function(){
target = -index*imgWidth; // 目标距离
var step = 210/30;// 运动次数 这个可以设置参数传入,像index一样,后面再加一位参数,这里就写死了
let speed = (target - imgBox.offsetLeft)/step // 每次步长是由目标距离减去当前距离
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); // 取整方便计算
if (target == imgBox.offsetLeft) {
clearInterval(timer);// 到达终点,我们要停止运动
}else{
imgBox.style.left = imgBox.offsetLeft + speed + "px";// 这是left值
}
},30);
}
// 自动轮播
function autoPlay() {
autoTimer = setInterval(function(){
// 这个逻辑和下一页点击的逻辑相同
imgIndex++;
if (imgIndex == imgBox.children.length) {
imgBox.style.left = 0;
imgIndex = 1;
}
animate(imgIndex);
},2000)
}
autoPlay() // 开始自动轮播
这块的js都是基础知识的组装,所以js基础还是很重要的。
我们来讲一下重点:
- 标签的创建与添加,还有克隆, 用到了字符串拼接的方法,innerHtML、 appendChild()、cloneNode()。标签用字符串创建出来放进数组,然后join(),是一个很使用的方法,以后会经常用到的。
- 事件循环绑定中
ctrlis[i].index = i
这一行是重点,它使你能够顺利找到你对谁绑定事件。 - 运动封装中我们首先要找到目标点,然后减去当前left值再除以运动次数来算出运动距离。这个是运动起来的关键。
-
ctrlis[index%ctrlis.length].className="active"
这一行代码是最不要忽视的,它是动态改变小圆点的样式,因为我们做了无缝滚动,但是小圆点还是只有我们能看到的图片的个数,重复的不算,所以要进行取余数判断,才不会报错。
好了,大概就是这么多内容,有什么不足之处还希望大家见谅。