原生js实现轮播图效果
步骤一:建立html基本布局
只有五张图片,却使用7张来轮播,这是为了实现无缝轮播, 开头放最后一张,结束时放第一张,
当进入最后一张时跳转到第二张,点击左边按钮进入最后一张时切换到第五张。
<body>
<div class="banner">
<ul class="list">
<li><a href="javascript:;"><img src="img/6.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="img/2.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="img/3.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="img/4.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="img/5.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="img/6.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="img/2.jpg" alt=""></a></li>
</ul>
<ul class="circle-list">
<li class="orange"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<span class="left"> < </span>
<span class="right"> > </span>
</div>
步骤二: css布局
<style>
* {
margin: 0;
padding: 0;
}
html body {
overflow: hidden;
}
ul li {
list-style: none;
}
a {
text-decoration: none;
}
input {
outline: none;
}
.banner {
position: relative;
width: 600px;
height: 350px;
margin: 200px auto;
overflow: hidden;
}
.banner .list {
position: absolute;
left: 0;
top: 0;
width: 4200px;
height: 350px;
}
.banner .list li {
float: left;
width: 600px;
height: 350px;
}
.list li a img {
width: 100%;
height: 100%;
}
.banner .left, .banner .right {
position: absolute;
width: 30px;
height: 30px;
background-color: #ccc;
top: 50%;
transform: translateY(-50%);
text-align: center;
line-height: 30px;
font-size: 24px;
opacity: 0;
transition: opacity 1s;
cursor: pointer;
}
.banner .left {
left: 0;
}
.banner .right {
right: 0;
}
.banner .circle-list {
position: absolute;
left: 50%;
bottom: 20px;
transform: translateX(-50%);
}
.circle-list li {
float: left;
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 10px;
background-color: rgba(255,255,255,.5);
cursor: pointer;
}
/* .orange定义了小圆点的背景颜色*/
.circle-list .orange {
background-color: orange;
}
</style>
步骤三:添加js逻辑
<script>
//获取元素
var left = document.querySelector('.banner .left');
var right = document.querySelector('.banner .right');
var box = document.querySelector('.banner');
var listNode = document.querySelector('.list');
var circleList = document.querySelectorAll('.circle-list li');
var circle = document.querySelector('.circle-list');
var timeAll = 600; //走完一张图片所用时间
var timestep = 20; //每走一步的时间,其实就是定时器当中的时间
var timer = null;
var autoTimer = null; //自动轮播定时器
var isMove = false; //判断当前是否在调用函数
box.onmouseenter = function (){
left.style.opacity = .5;
right.style.opacity = .5;
clearInterval(autoTimer);
}
box.onmouseleave = function (){
left.style.opacity = 0;
right.style.opacity = 0;
autoRun();
}
listNode.style.left = -600 + 'px';//无缝之后,轮播图默认显示的不再是之前第一张而是之前的最后一张
function move(flag) {
//判断元素是否在移动
//处理连续点击,元素叠加移动的bug
if(isMove){
return;
}
isMove = true;
setTimeout(function () {
isMove = false;
},700)
if (typeof flag == 'boolean'){
if(flag){
var dis = -600;//每点一次走的距离
}else{
var dis = 600;
}
}else {
dis = flag - listNode.offsetLeft;//点击小圆点传的是元素最终的位置,通过这个最终位置拿到移动的距离
}
var lastDis = listNode.offsetLeft + dis;
var step = dis/(timeAll/timestep); //每走一步的距离
//设置定时器
timer = setInterval(function () {
var left = listNode.offsetLeft + step;
if(left == lastDis){
clearInterval(timer); //一张走完清理定时器
//实现无缝逻辑
if(left == -3600){
left = -600;
}else if(left == 0){
left = -3000;
}
}
listNode.style.left = left + 'px';
},timestep)
// 小圆点点击变色
var index = Math.abs(lastDis / 600) - 1;
if(index < 0){
index = 4;
}
//排他法先让所有小圆点变色
for(var i = 0; i < circleList.length; i++){
circleList[i].className = '';
}
circleList[index % 5].className = 'orange';
// 同步点击按钮和自动轮播下标
autoIndex = (index % 5) + 1;
}
right.onclick = function(){
move(true);
}
left.onclick = function () {
move(false);
}
// 点击小圆点移动到对应图片
for(var i = 0; i < circleList.length; i++){
circleList[i].index = i;
circleList[i].onclick = function () {
move((this.index + 1) * -600);
// 同步小圆点按钮和自动轮播下标
autoIndex = this.index + 1;
}
}
// 图片自动轮播
var autoIndex = 1;
autoRun();
function autoRun() {
autoTimer = setInterval(function () {
autoIndex ++;
move(autoIndex * -600);
if(autoIndex == 6){
autoIndex = 1;
}
},2000)
}
</script>
总结:
第一步: 结构 结构牢记
第二步:css 外面小盒子根据图片的宽度进行设置 内部大盒子 宽度是根据图片的个数进行的设置的
第三步: js行为
- 1、点击按钮让图片先动起来(只点击右侧) 每次点击要准备走的距离都是-600,这个距离需要用定时器慢慢走,
需要求每一步的距离 元素起始位置我们是可以获取到的, 结束位置我们也求出来; - 2、 看什么时候元素停止,当刚好元素走的位置和开启求出来的结束位置一样的实惠,停止定时器;
- 3、左边按钮和右边按钮 几乎一致,
只是点左边按钮的时候,元素要准备走的距离是600,其它的都不变,因此封装函数move(flag)
函数传参为true就是点右 false就是点左 - 4、无缝的操作 结构需要变化 最前面加最后一张 最后面加第一张; 在清除定时器的时候
,去判断是否元素走到了最后一张的位置和第一张的位置,如果走到,让元素顺便到相应的位置 - 5、小圆点变色 排他 关键点在求出哪一个小圆点变色,就是要拿到小圆点变色的下标,通过元素最终位置去求
- 6、点击小圆点,图片移动对应位置 要传递元素准备移动的最终位置 跟点击的小圆点下标相关,move里面参数要根据类型进行判断
到底是点的按钮还是点的小圆点,因为传过来的参数不同 - 7、自动轮播 , 根据图片的下标进行move 传的也是元素准备移动的最终位置, 下标需要进行判断 为6 变回1
- 8、自动轮播鼠标行为的同步 鼠标移入清除自动轮播 鼠标移出重启自动轮播
- 9、移入之后,鼠标点击按钮或者小圆点,都要去把自动轮播的下标值 进行更新, 否则没法同步;