如何通过原生JS实现自动轮播图?

轮播图在Web前端很常见,现在我也是刚开始学Web。
主要实现轮播图的自动播放,以及点击按钮可以切换对应的图片。
总结一下最近写轮播图的方法和注意点叭~

以下是轮播图的效果,在图上加了图片的序号><
完成的结果
接下来一起开始从头的制作叭!

1. html文件

<body>
    <!-- 注意如果还有外层的话记得加上定位,为了offsetLeft的准确 -->
    <div class="banner">
        <!-- 轮播图的容器 -->
        <ul class="slide">
            <li>
                <a href="#">
                    <img src="images/0.jpg" alt="">
                </a>
            </li>
            <li>
                <a href="#">
                    <img src="images/1.jpg" alt="">
                </a>
            </li>
            <li>
                <a href="#">
                    <img src="images/2.jpg" alt="">
                </a>
            </li>
            <li>
                <a href="#">
                    <img src="images/3.jpg" alt="">
                </a>
            </li>
        </ul>
        <!-- 轮播点的容器 事先无法确定图的个数 所以不写死li的个数 后面通过js自动插入 -->
        <ul class="dots"></ul>
    </div>
</body>

大致的意思就像下图:

通过很宽的ul(绿色)来装如所有的轮播图li,让li左浮动,使他们都在一行上。然后通过刚好允许一张图片显示的定宽的盒子div(橙色)包在ul的外面,这样,我们通过ul的left来移动ul,然后将div设为overflow:hidden,我们就只能看见一张图片啦~

第一排是left:0,第二排是left:-500px,即将第二个li移入div里。
轮播图大致理解

2. CSS文件

将页面布局成如下效果:
CSS布局
注意测试的时候可以不给div加上overflow:hidden属性,这样会看的更清楚ul是怎么运作的哦~

*{
    margin: 0;
    padding: 0;
}
body{
    background-color: #000;
}
.banner{
    position: relative;    /*point 1*/
    margin: 50px auto;
    width: 500px;
    overflow: hidden;
}
.slide{
    position: relative;   /*point 1*/
    width: 3000px;
    overflow: hidden;   /*清除浮动*/
}
.slide li{
    float: left;
}
.slide li img{
    width: 500px;
}
.dots{
    overflow: hidden;  
    display: inline-block;
    position: relative;
    left: 50%;
    transform: translateX(-50%); 
}
.dots li{
    /* 这里用浮动的话会有问题,也不太清楚为什么,js的点击事件this不准确 */
    display: inline-block;     /*point 2*/
    cursor: pointer;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background-color: ivory;
    margin: 0 4px;
}
.dots .selected{
    background-color: lightcoral;
}

CSS的样式自己写就可以,比较简单,但是有几个地方想要特别强调一下,我自己写的时候有几个细节很容易导致错误,这些地方我都在代码上标上了备注!!

  • point 1
    首先一定一定一定!!要在ul上加上定位!!
    否则当在JS中设置left的值的时候就移动不了,因为left属性是在有position的时候才有意义的。

    其次!一定一定一定!!要在ul外的每一个父元素都加上定位!!
    因为在JS中移动是通过控制offsetLeft属性,而offsetLeft属性和定位息息相关,可以参照https://blog.csdn.net/w390058785/article/details/80461845 这个博客。(当时我不知道这个卡了可久TT)

  • point 2
    还有一个点是轮播点用的是inline-block,而不能用float:left。
    这个我不懂为啥要这样,如果有大佬知道的话,欢迎教教我~
    如果我用浮动的话,JS的点击就会不准确,this没法得到对应的li。

3. JS文件

  • 首先我们要来实现一个函数,来封装移动ul的功能。

function animate(obj, target, callback)
obj:需要移动的元素,target:移动的目标位置,callback:回调函数

函数的代码如下:

function animate(obj, target, callback) {
    obj.timer = setInterval(function () {
        step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            if (callback) {
                callback();
            }
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15);
}

这里是通过设置一个定时器来每隔15ms移动一段距离,看起来仿佛是动画一样的效果,然后通过step来设置步长,每次移动的距离都逐渐减小,有一种运动的先快后慢的效果。

step = step > 0 ? Math.ceil(step) : Math.floor(step);
这个是因为step因为使用了除法,会有一些误差,有小数,所以向上下取整。

  • 完成上面的函数后,我们可以开始写轮播图的JS逻辑啦!

对应的解释,我已经写在了备注里,请放心食用~

// 移动轮播图容器的函数
// obj是移动的对象,即ul;target是移动的目标位置,即ul的left的值;callback是回调函数
function animate(obj, target, callback) {
    obj.timer = setInterval(function () {
        step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            if (callback) {
                callback();
            }
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15);
}

window.addEventListener('load', function () {
    var num = 0;
    var banner = document.querySelector('.banner');
    var slide = document.querySelector('.slide');
    var dots = document.querySelector('.dots');
    // 首先动态插入轮播点,插入的个数等于slide里的li的个数
    for (var i = 0; i < slide.children.length; i++) {
        var dot = document.createElement("li");
        dot.setAttribute('index', i);//设置index属性,方便后面点击轮播点,拿到对应的索引
        dot.addEventListener('click', function () {
            console.log(this);
            // 点击轮播点后,改变被点击的点的颜色
            // 点击某个轮播点后,将所有点类名设置为空
            for (var i = 0; i < dots.children.length; i++) {
                dots.children[i].className = '';
            }
            // 将被点击的点的类名设置为selected
            this.className = 'selected';
            var index = this.getAttribute('index');
            num = index;
            console.log(index);

            // 取得ul移动的距离,即索引*轮播图的宽度(从0开始),注意这里是向左移动,所以取负的
            var target = -index * banner.offsetWidth;
            animate(slide, target);
        })
        dots.appendChild(dot);
    }
    // 插入完成后,将第一个轮播点设为被选择状态
    dots.children[0].className = 'selected';

    // 将第一个图克隆,粘贴到slide的最后面,这样最后一张图播放到第一张图时才能平滑向后滑
    // 因为是在生成小图标后添加图片,所以自动生成的小图标并不会增多
    var first = slide.children[0].cloneNode(true);
    slide.appendChild(first);

    //设置自动播放,这里的num要配合点击事件的index,保证从被点击的地方继续自动播放
    var Timer = setInterval(function () {
        //到了最后一张的克隆的图片
        if (num == slide.children.length - 1) {
            num = 0;
            slide.style.left = 0;   //设置为第一张图片,然后马上会滑向第二张图片,这样实现无缝连接
        }
        ++num;
        var target = -num * banner.offsetWidth;
        animate(slide, target);
        //改变对应的点
        for (var i = 0; i < dots.children.length; i++) {
            dots.children[i].className = '';
        }
        dots.children.className[num % dots.children.length] = 'selected';
    }, 3000);

    // 鼠标放上停止自动播放
    banner.addEventListener('mouseover', function () {
        clearInterval(Timer);
        Timer = null;
    })

    // 鼠标离开继续播放
    banner.addEventListener('mouseleave', function () {
        Timer = setInterval(function () {
            //到了最后一张的克隆的图片
            if (num == slide.children.length - 1) {
                num = 0;
                slide.style.left = 0;   //设置为第一张图片,然后马上会滑向第二张图片,这样实现无缝连接
            }
            ++num;
            var target = -num * banner.offsetWidth;
            animate(slide, target);
            //改变对应的点
            for (var i = 0; i < dots.children.length; i++) {
                dots.children[i].className = '';
            }
            dots.children[num % dots.children.length].className = 'selected';
        }, 3000);
    })
})

到这里就完成我们的轮播图啦~
第一次写Web的笔记,有什么问题的话欢迎指正~

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值