【前端面试之手写代码】用js手写一个轮播图

轮播图功能分析:

  • 可以自动循环
  • 点击轮播图下面的上一页下一页按钮,轮播图也可以进行播放
  • 当鼠标放在轮播图上时,停止播放,当鼠标离开时,则继续播放

它涉及到了两个定时器: 第一个定时器是用更换图片的,第二个定时器用来每隔15ms往前移动图片10px。这两点我在看这个原理的时候,超级惊讶,就没想到一个轮播图往前移动也会有一个定时器来播放它。大家可以猜一下,定时器有setTimeOut和setInterval两个定时器,应该用哪个?两个定时器都要用到setInterval,不停的播放!

页面样式实现

 <div id="box">
    <ul class="pic_list">
        
   <li class="item"><img class="pic" src="img/img2.jpg" alt="">li>
   <li class="item"><img class="pic" src="img/img3.jpg" alt="">li>
   <li class="item"><img class="pic" src="img/img4.jpg" alt="">li>
   
ul>
div>
<div class="btn">
    <button id="prev">前一张button>
    <button id="next">后一张button>
div>

设定轮播三张图片:

  1. box用于定于轮播框的大小,宽400px、高300px,并且水平居中
  2. pic_list定义宽400%、高300px,能够放入所有的图片
  3. item将图片浮动起来,所有图片放在了一行显示
#box {
    width: 400px;
    height: 300px;
    position: relative;
    margin: 0 auto;
    overflow: hidden;
}

.pic_list {
    list-style: none;
    width: 500%;
    height: 300px;
    position: relative;
    padding: 0;
    margin: 0;
    top: 0px;
}

.pic {
    width: 400px;
    height: 300px;
    padding: 0;
    margin: 0;
}

.item {
    float: left;
}

.btn {
    margin: 10px auto;
    width: 150px;
}

功能分块介绍

1. 初始化:

获取pic_list,用于通过style上的left改变位置,点击下一张的话,向左移动,点击上一张,则向右移动。

let imags = document.querySelector('.pic_list');//同样移动图片

获取轮播图有几张图片

 let length = document.querySelectorAll('.item').length;//减去在头和尾部加的两张图片

初始化列表最开始的位置

 imags.style.left = '0' + 'px';//初始化列表最开始的位置

这是一些参数,time是第一个定时器(用于跳到下一张,每隔2400ms便跳转到下一张)。time2第二个定时器(图片每隔15ms便向左移动10px)。distance记录图片一共移动的距离。index记录图片当前的索引

 let time = null, time2 = null, distance = 0, index = 1;

2. init函数,轮播图中的一些鼠标事件都会在这里定义。

  • 获取页面元素
 const box = document.querySelector('#box');
 const pre = document.querySelector('#prev');
 const next = document.querySelector('#next');
  • 点击上一页,触发动画,将值1传入(用来标识我要看上一张)
  • 点击下一页,触发动画,将值2传入(用来标识我要看下一张)
pre.onclick = function () {
   animate(1);
}
next.onclick = function () {
    animate(2);
}
  • 鼠标移动到图上时,动画就会停止。用到的监听函数,并清除定时器
box.addEventListener('onmouseenter', function () {
    clearInterval(time);//鼠标进入清除定时器
}, 2500);
  • 鼠标移开图片上时,动画会继续。
box.addEventListener('onmouseleave', function () {
    // 鼠标离开开启定时器
    time = setInterval(function () {
        // clearInterval(time2)
        animate(2);
    }, 2500)
})

3. 动画函数

  • 首先就要判断time2是否存在,如果还没到时间,就不会去执行这个动画
  • 定义一个setInterval
  • 判断是前进还是后退
  • distance就在这里用到了,用来记录这个图片前进了多少,后退了多少
  • 图片要移动咯。 imags.style.left = (parseInt(imags.style.left) + step) + 'px'
  • 判断当前distance是否已经移动了他自己的宽度,到下一张图片了。
  • 是的话,清除time2,并置为Null。根据传入的Num值,index加一或者减一。
  • 此时有两种临界情况:
    • 如果index移动到了最后一张图片的后面(下标从1开始)。index跑到第1个,然后图片的位置移动到第一张图片的位置上。
    • 如果index移动到了第一张图片的前面,index就对应的最后一张图片,图片的位置移动到最后一张图片的位置上。
function animate(num) {
    console.log(time2)
    if (!time2) {
        time2 = setInterval(function () {
            let step = num === 1 ? 10 : -10;
            distance += Math.abs(step);
            imags.style.left = (parseInt(imags.style.left) + step) + 'px'
            if (distance >= 400) {
                clearInterval(time2)//重新计时
                time2 = null;
                distance = 0;//重新计算距离
                if (step > 0) index -= 1;//点击pre,index图片列表就-1
                if (step < 0) index += 1;//点击next,index图片列表就+1

                if (index > length) {//已经滑到图片列表的尾部
                    index = 1;
                    imags.style.left = 0 + 'px';

                } else if (index < 1) {
                    index = length;
                    imags.style.left = (-400) * (length - 1) + 'px';
                }
                console.log(index)
            }

        }, 15)
    }
}

这样写其实有点bug:

小bug

这里回到页面样式这部分,一开始我很不理解为什么要在头和尾处添加两张重复的图片,为什么要添加?作用是啥呢?后来我就把他删了,也能实现出来。但是出现了这样的bug,这时候才明白添加这两张图片是很有必要的。比如说当图片运行到最后一张的时候,此时index=3,还会再继续往前进,但是前面是空白,当移动400px的时候,此时index=4,才会进入临界条件,imags的位置重新赋值,移动到第一个图片但是这段时间的空白怎么办?确实可以从最后一个移动到第一个,但是在移动的过程中会有空白出现,此时在图片列表左右添加上两张图片就不会出现这种情况了,下面的代码,完美的解决了这个问题:

//这一块记得修改哈
let length = document.querySelectorAll('.item').length - 2;
imags.style.left = '-400' + 'px';//初始化列表最开始的位置

function animate(num) {
    if (!time2) {
        time2 = setInterval(function () {
            let step = num === 1 ? 10 : -10;
            distance += Math.abs(step);
            imags.style.left = (parseInt(imags.style.left) + step) + 'px'
            if (distance >= 400) {
                clearInterval(time2)//重新计时
                time2 = null;
                distance = 0;//重新计算距离
                if (step > 0) index -= 1;//点击pre,index图片列表就-1
                if (step < 0) index += 1;//点击next,index图片列表就+1

                if (index > length) {//已经滑到图片列表的尾部
                    index = 1;
                    imags.style.left = -400 + 'px';

                } else if (index < 1) {
                    index = length;
                    imags.style.left = (-400) * length + 'px';
                }
                console.log(index)
            }

        }, 15)
    }
}

你可能感兴趣的:(前端面试总结,javascript,前端,html)