手写一个原生轮播图
- 被框架限制太久,很多简单的功能都用框架了,但是框架有他的局限性,这时候原生JS手写一个小功能就很香了,但是太久没用,又有些忘记了,所以今天打算手写一个轮播图,复习一下原生js的使用,和轮播图用到的思想
- 我们再来重温一下轮播的实现原理,用一个展示图片的盒子这个盒子固定一张图片大小,超出隐藏,把图片横向排列,朝一个方向移动,每次移动一张图片的距离,这样,虽然页面是一个拥有多张图片的超长集合图片,但是每次用户看到的都是一张完整的图片,我们需要做的就是用定时器控制图片移动的时间和距离,点击按钮同理
第一步:构建页面文档
<div class="all" id='box'>
<!-- 图片 -->
<div class="screen">
<ul>
<li><img src="./lunboimage/timg1.jpg" width="500" height="200"></li>
<li><img src="./lunboimage/timg2.jpg" width="500" height="200"></li>
<li><img src="./lunboimage/timg3.jpg" width="500" height="200"></li>
<li><img src="./lunboimage/timg4.jpg" width="500" height="200"></li>
<li><img src="./lunboimage/timg5.jpg" width="500" height="200"></li>
<li><img src="./lunboimage/timg1.jpg" width="500" height="200"></li>
</ul>
<ol>
<!-- 页码 -->
<li class="current">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ol>
</div>
<!-- 左右箭头 -->
<div id="arr">
<span id="left"><</span>
<span id="right">></span>
</div>
</div>
小结:分为三个部分,轮播区域,页码区域,左右箭头区域
第二部:样式区域
* {
padding: 0;
margin: 0;
list-style: none;
border: 0;
}
.all {
width: 500px;
height: 200px;
padding: 7px;
border: 1px solid #ccc;
margin: 100px auto;
position: relative;
}
.screen {
width: 500px;
height: 200px;
overflow: hidden;
position: relative;
}
.screen li {
width: 500px;
height: 200px;
overflow: hidden;
float: left;
}
.screen ul {
/* 此处一定要用定位(子绝) */
position: absolute;
left: 0;
top: 0;
/*要足够宽才放到一行里*/
width: 3000px;
}
.all ol {
position: absolute;
right: 10px;
bottom: 10px;
line-height: 20px;
text-align: center;
}
.all ol li {
float: left;
width: 20px;
height: 20px;
background: #fff;
border: 1px solid #ccc;
margin-left: 10px;
cursor: pointer;
}
.all ol li.current {
background: yellow;
}
#arr {
/* display: none; */
}
#arr span {
width: 40px;
height: 40px;
position: absolute;
left: 5px;
top: 50%;
margin-top: -20px;
background: #000;
cursor: pointer;
line-height: 40px;
text-align: center;
font-weight: bold;
font-family: '黑体';
font-size: 30px;
color: #fff;
/*透明度:这个是指全透明*/
opacity: 0.3;
border: 1px solid #fff;
}
#arr #right {
/*距离父元素右边5像素*/
right: 5px;
/*代表把left的值清空(设置为默认值)*/
left: auto;
}
小结:首先 初始化样式,然后让页面中5张图片横向排列,然后将展示图片那个盒子设置overflow:hidden,超出隐藏,这样就只能刚好看到一张图片,剩下的被隐藏了,
重点部分 :功能实现(分步代码)
- 准备工作:
//1 找到大盒子
var box = document.querySelector('#box');
//2 找到箭头
var arr = document.querySelector('#arr');
//3 找到ul
var ul = document.querySelector('ul');
//4 找到放图片的div的宽度
var screenW = document.querySelector('.screen').offsetWidth;
//5. 找到ol下面的所有li(也就是找到所有页码)
var pageList = document.querySelectorAll('ol>li');
小结:这里使用dom的document类型的节点获取页面节点元素,分别找到了盒子,左右箭头和放置图片的盒子,以及他的宽度,还有所有页码的集合
- 功能实现函数
//1 移动动画封装函数 参数1,移动的目标,参数2,移动的距离
function animate(obj, target) {
// 每次先停止上一个计时器
clearInterval(obj.timerID);
obj.timerID = setInterval(function() {
// 获得它当前位置 要求子元素和父级元素都要定位(切记)
var current = obj.offsetLeft;
// 移动距离减去当前距离,每次前进10px,直到到达,到达后停止定时器
if (Math.abs(target - current) > 10) {
// 走一步
current += target > current ? 10 : -10;
// 赋值给left
obj.style.left = current + "px";
} else {
obj.style.left = target + "px";
}
if (current == target) {
clearInterval(obj.timerID);
}
}, 10);
};
//2 下一页的函数
function nextPage() {
// 在下一页点击事件里做个判断,如果是最后一张,就闪现到第一张下标0的那张
if (index == ul.children.length - 1) {
index = 0;
ul.style.left = 0;
}
// 到达后页码++
index++;
// 用最新的目标下标*宽度赋值给ul current = -index * screenW;
// 参数1:移动哪个元素 参数2:目标位置
animate(ul, -index * screenW);
// 先让所有页码去掉高亮
for (var i = 0; i < pageList.length; i++) {
pageList[i].className = "";
}
// 如果是最后一张(看起来是第一张的那张图片)
if (index == ul.children.length - 1) {
//就让下标0的页码高亮
pageList[0].className = "current";
} else {
// 还要当前显示第几个图片,就让第几个页码高亮
pageList[index].className = "current";
}
}
//3 遍历所有页码给它们加点击事件
for (var i = 0; i < pageList.length; i++) {
// 先把下标存到每个页码身上
pageList[i].setAttribute('index', i);
pageList[i].onclick = function() {
// 一开始判断,如果当前图片是最后一页,就闪现到第一页
if (index == ul.children.length - 1) {
index = 0;
ul.style.left = 0;
}
//获取被点击的页码的下标
var idx = this.getAttribute('index');
// 如果你当前是第一页,并且点击的是最后一个页码
if (index == 0 && idx == pageList.length - 1) {
//闪现到最后一页
index = ul.children.length - 1;
ul.style.left = -index * screenW + "px";
}
// 点哪个下标的页码就让对应的图片到对应的下标去
animate(ul, -idx * screenW);
// 还要让记录图片下标的index更新成对应的下标
index = idx;
//排他去掉高亮
for (var j = 0; j < pageList.length; j++) {
pageList[j].className = "";
}
this.className = "current";
}
}
小结:这一步首先是一个动画效果函数,他的第一个参数是对象,第二个是目标移动距离,所以移动时先停止计时器。然后计算移动位子,在移动到时先停止,等待下一个计时器开始,,下一页函数就是调用动画效果函数,用第几页对应的index乘宽度,得到最新坐标,传给动画函数,这里要注意一个最后一张和第一张的情况,然后遍历所有页码,给他添加点击事件,点哪一张就到哪一张下标,然后排他去除样式,给当前高亮,
- 效果功能
var timerID = setInterval(nextPage, 2200);
//1 大盒子鼠标移入:停止计时器,页面停止运动
box.onmouseover = function() {
//左右点击按钮隐藏
arr.style.display = "block";
//停止计时器
clearInterval(timerID);
}
//2 大盒子鼠标移出:开始计时器,页面开始运动
box.onmouseout = function() {
arr.style.display = "none";
timerID = setInterval(nextPage, 2200);
}
// 准备一个变量index,默认从0开始,因为默认显示下标0的图片
var index = 0;
//3 下一页的点击事件:调用下一页事件
document.getElementById('right').onclick = function() {
nextPage();
};
//4 完成上一页点击事件
document.getElementById('left').onclick = function() {
// 在上一页点击事件里做个判断,如果是第一张,就闪现到最后一张,然后再上一张
if (index == 0) {
//闪现到最后一张(也就是看起来内容是第一张的图片,下标是长度-1)
index = ul.children.length - 1;
ul.style.left = -index * screenW + "px";
}
index--;
animate(ul, -index * screenW);
//排他,所有样式取消
for (var i = 0; i < pageList.length; i++) {
pageList[i].className = "";
}
// 图片是下标几,就取出下标几的页码
pageList[index].className = "current";
};
小结:思考逻辑,调用上面实现的代码,实现功能
功能实现(完整代码)
//!!!!!!!!!!!!!!!首先 准备工作!!!!!!!!!!!!
//1 找到大盒子
var box = document.querySelector('#box');
//2 找到箭头
var arr = document.querySelector('#arr');
//3 找到ul
var ul = document.querySelector('ul');
//4 找到放图片的div的宽度
var screenW = document.querySelector('.screen').offsetWidth;
//5. 找到ol下面的所有li(也就是找到所有页码)
var pageList = document.querySelectorAll('ol>li');
//!!!!!!!!!!!!!!!!!!!!!!!!!其次,功能实现函数!!!!!!!!!!!!!!!!!!!!!
//1 移动动画封装函数 参数1,移动的目标,参数2,移动的距离
function animate(obj, target) {
// 每次先停止上一个计时器
clearInterval(obj.timerID);
obj.timerID = setInterval(function() {
// 获得它当前位置 要求子元素和父级元素都要定位(切记)
var current = obj.offsetLeft;
// 移动距离减去当前距离,有多说明没到,每次前进10px,直到到达,到达后停止定时器
if (Math.abs(target - current) > 10) {
// 走一步
current += target > current ? 10 : -10;
// 赋值给left
obj.style.left = current + "px";
} else {
obj.style.left = target + "px";
}
if (current == target) {
clearInterval(obj.timerID);
}
}, 10);
};
//2 下一页的函数
function nextPage() {
// 在下一页点击事件里做个判断,如果是最后一张,就闪现到第一张下标0的那张
if (index == ul.children.length - 1) {
index = 0;
ul.style.left = 0;
}
// 让index++
index++;
// 用最新的-下标*宽度赋值给ul
// var current = -index * screenW;
// ul.style.left = current + "px";
// 参数1:移动哪个元素
// 参数2:目标位置
animate(ul, -index * screenW);
// 先让所有页码去掉高亮
for (var i = 0; i < pageList.length; i++) {
pageList[i].className = "";
}
// 如果是最后一张(看起来是第一张的那张图片)
if (index == ul.children.length - 1) {
//就让下标0的页码高亮
pageList[0].className = "current";
} else {
// 还要当前显示第几个图片,就让第几个页码高亮
pageList[index].className = "current";
}
}
//3 遍历所有页码给它们加点击事件
for (var i = 0; i < pageList.length; i++) {
// 先把下标存到每个页码身上
pageList[i].setAttribute('index', i);
pageList[i].onclick = function() {
// 一开始判断,如果当前图片是最后一页,就闪现到第一页
if (index == ul.children.length - 1) {
index = 0;
ul.style.left = 0;
}
//获取被点击的页码的下标
var idx = this.getAttribute('index');
// 如果你当前是第一页,并且点击的是最后一个页码
if (index == 0 && idx == pageList.length - 1) {
//闪现到最后一页
index = ul.children.length - 1;
ul.style.left = -index * screenW + "px";
}
// 点哪个下标的页码就让对应的图片到对应的下标去
animate(ul, -idx * screenW);
// 还要让记录图片下标的index更新成对应的下标
index = idx;
//排他去掉高亮
for (var j = 0; j < pageList.length; j++) {
pageList[j].className = "";
}
this.className = "current";
}
}
//!!!!!!!!!!!!!!效果调用功能!!!!!!!!!!!
var timerID = setInterval(nextPage, 2200);
//1 大盒子鼠标移入:停止计时器,页面停止运动
box.onmouseover = function() {
//左右点击按钮隐藏
arr.style.display = "block";
//停止计时器
clearInterval(timerID);
}
//2 大盒子鼠标移出:开始计时器,页面开始运动
box.onmouseout = function() {
arr.style.display = "none";
timerID = setInterval(nextPage, 2200);
}
// 准备一个变量index,默认从0开始,因为默认显示下标0的图片
var index = 0;
//3 下一页的点击事件:调用下一页事件
document.getElementById('right').onclick = function() {
nextPage();
};
//4 完成上一页点击事件
document.getElementById('left').onclick = function() {
// 在上一页点击事件里做个判断,如果是第一张,就闪现到最后一张,然后再上一张
if (index == 0) {
//闪现到最后一张(也就是看起来内容是第一张的图片,下标是长度-1)
index = ul.children.length - 1;
ul.style.left = -index * screenW + "px";
}
index--;
animate(ul, -index * screenW);
//排他,所有样式取消
for (var i = 0; i < pageList.length; i++) {
pageList[i].className = "";
}
// 图片是下标几,就取出下标几的页码
pageList[index].className = "current";
};
作者:coolFish
链接:https://juejin.im/post/6891634318738161678
来源:掘金