Javascript实现轮播图功能

刚结束了一个月的html+css+JavaScript的学习。学JavaScript一定会做一个轮播图的案例,因为太经典了。


用Gifcam做出来的gif图有点大,CSDN要求上传的图片在5M以内,5M的话就看不到轮播的效果了,也没专门去找压缩软件,所以就不放效果图了,把用到的图片放到末尾了,有需要的把html中图片路径改一下就能用了。提醒一下,用到的动画函数和轮播图的功能实现,都是通过引入js文件的形式实现的,在html里可以看到,两个文件的引用。

功能需求

  1. 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
  2. 点击右侧按钮依次,图片往左播放一张,以此类推,左侧按钮同理。
  3. 图片播放的同时,下面小圆圈模块跟随一起变化。
  4. 点击小圆圈,可以播放相应图片。
  5. 鼠标不经过轮播图,轮播图也会自动播放
  6. 鼠标经过轮播图模块,自动停止播放。

案例分析

  • 按钮的显示隐藏,根据鼠标事件设置display属性即可
  • 动态生成下面的小圆圈。小圆圈的数量与图片的数量是一致的。首先可以获得ul里面图片的个数,创建节点,动态生成小圆圈,再插入节点,放到ol里面。
  • 点击某个小圆圈,被点击的小圆圈颜色会与其他的不一样,这里利用排他思想就可以实现
  • 点击小圆圈移动图片:此时用到下面的动画函数,将js文件引入。在创建小圆圈的同时,加上一自定义属性存储索引号,点击某个小圆圈时,就让图片滚动 小圆圈的索引号乘以图片的宽度 作为ul的移动距离。
  • 无缝滚动:克隆ul的第一个li节点,放到ul的最后面。声明一个num变量,点击一次,自增1,让这个变量乘以图片的宽度,就是ul的滚动距离。当图片滚动到克隆的最后一张图片时,让ul快速的,不做动画的跳到最左侧:left:0;
  • 自动播放:就像我们点击了下一张的按钮,所以我们添加一个定时器,手动的调用右侧按钮的点击事件
  • 节流阀:当我们连续点击下一张或上一张按钮,图片会快速的移动,为了防止播放过快。可以利用回调函数,添加一个变量来控制,上一个动画执行完毕后,再去执行下一个动画,让事件无法连续触发,锁住函数和解锁函数。

动画函数

在上轮播图前,先说一下这个动画函数,轮播图中图片的移动就是用的这个函数。

  • 函数名为animate,参数obj为目标对象(必须有定位),target为目标位置,callback为回调函数
  • 上来先清除计时器,再添加计时器,确保只能有一个计时器,否则每调用一次函数,就添加一个定时器。
  • 将定时器作为对象的属性,不作为变量,避免多个对象调用该函数,在内存中开辟多个空间存储变量,浪费内存资源。同时每个元素都有自己单独的定时器,不会引起歧义。
  • step为每次移动的距离,由目标位置减去现在的位置再除以一个数所得,移动的距离越来越小,以此来实现缓动的效果。
  • 由于步长的计算会出现小数,所以可能出现最后与目标位置相差一些距离,所以调用Math里的方法对步长进行了处理。
  • 回调函数:函数作为一个参数,将这个函数作为参数传递到另一个函数里,当那个函数执行完后,再执行传进去的这个函数,这个过程就叫回调。
function animate(obj, target, callback) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
        //计算步长值   注意 步长值应为整数 
        var step = (target - obj.offsetLeft) / 20;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            //回调函数写到定时器结束里面

            //简易写法 利用短路原理
            callback && callback();
        } else {
            obj.style.left = obj.offsetLeft + step + 'px';
        }
    }, 15)
}

轮播图结构的搭建

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .w {
            position: relative;
            width: 980px;
            height: 450px;
            margin: 100px auto;
            overflow: hidden;
        }

        .w ul {
            position: absolute;
            left: 0;
            top: 0;
            width: 600%;
            height: 100%;
        }

        .w ul li {
            float: left;
            width: 980px;
            height: 100%;
            list-style: none;
        }

        /*  .w ul li a {
            display: block;
            width: 100%;
            height: 100%;
        }
 */
        .w ul img {
            width: 100%;
            height: 100%;
        }

        .w .circle {
            position: absolute;
            left: 50%;
            bottom: 5px;
            transform: translateX(-50%);
        }

        .w .circle li {
            list-style: none;
            float: left;
            width: 10px;
            height: 10px;
            margin: 3px;
            border-radius: 50%;
            background-color: #ffffff;
            cursor: pointer;
        }

        .w>a {
            display: none;
            position: absolute;
            top: 50%;
            width: 20px;
            height: 40px;
            background-color: #585757;
            font-size: 22px;
            line-height: 36px;
            text-align: center;
            color: #ffffff;
            text-decoration: none;
            z-index: 1;
        }

        .w .arrow-1 {
            left: 15px;
        }

        .w .arrow-2 {
            right: 15px;
        }
    </style>
    <script src="animate.js"></script>
    <!-- lunbo的js文件里要用到animate文件里的方法 所以animate要放到上面 -->
    <script src="lunbotu.js"></script>
</head>

<body>
    <div class="w">
        <a href="javascript:void(0);" class="arrow-1">&lt;</a>
        <a href="javascript:void(0);" class="arrow-2">&gt;</a>
        <ul>
            <li>
                <a href="javascript:void(0);"><img src="../../../images/Bing.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:void(0);"><img src="../../../images/LenticularVideo.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:void(0);"><img src="../../../images/LoughriggTarn.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:void(0);"><img src="../../../images/SaltonSea.jpg" alt=""></a>
            </li>

        </ul>

        <ol class="circle">

        </ol>
    </div>
</body>

</html>

轮播图的核心

window.addEventListener('load', function () {
    //获取元素
    var arrow_1 = document.querySelector('.arrow-1');
    var arrow_2 = document.querySelector('.arrow-2');
    var w = document.querySelector('.w');
    var width = w.offsetWidth;
    w.addEventListener('mouseenter', function () {
        arrow_1.style.display = 'block';
        arrow_2.style.display = 'block';
        clearInterval(timer);
        //清除计时器变量
        timer = null;
    })
    w.addEventListener('mouseleave', function () {
        arrow_1.style.display = 'none';
        arrow_2.style.display = 'none';
        timer = setInterval(() => {
            //手动调用点击事件
            arrow_2.click();
        }, 2000);
    })

    var ul = w.querySelector('ul');
    var ol = w.querySelector('.circle');
    for (var i = 0; i < ul.children.length; i++) {
        //创建一个小 li
        var li = document.createElement('li');
        //给li加一个自定义属性
        li.setAttribute('data-index', i);
        //我们可以在生成li 的同时 绑定事件 排他思想 
        li.addEventListener('click', function () {
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].style.backgroundColor = '';
            }
            this.style.backgroundColor = 'darkorange';
            //点击小圆圈 移动图片 移动的是ul
            //ul 移动的距离 小圆圈的索引号 乘以 图片的宽度 注意移动距离是负值
            //当我们点击了某个li 就拿到当前li的索引号
            var index = this.getAttribute('data-index');
            //当我们点击了某个li 就要把这个li的索引号 给num
            num = index;
            //当我们点击了某个li  也要把这个li的索引号 给circle
            circle = index;
            // num = circle = index;
            animate(ul, -index * width);

        })
        //把小li插入到ol里面
        ol.appendChild(li);
    }
    ol.children[0].style.backgroundColor = 'darkorange';

    //克隆第一张图片 放到ul最后面
    var first = ul.children[0].cloneNode(true);
    ul.appendChild(first);
    //点击右侧按钮,图片滚动一张
    var num = 0;
    //circle控制小圆圈的播放
    var circle = 0;
    //右侧按钮
    //节流阀
    var flag = true;
    arrow_2.addEventListener('click', function () {
        if (flag) {
            flag = false;
            //如果走到了最后复制的一张  此时 我们的ul要快速复原  
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * width, () => {
                flag = true;
                //打开节流阀
            });
            //点击右侧按钮 小圆圈跟随一起变化 可以再声明一个控制小圆圈播放的变量
            circle++;
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].style.backgroundColor = '';
            }
            //留下当前的小圆圈的
            ol.children[circle % ol.children.length].style.backgroundColor = 'darkorange';

        }
    })

    //左侧按钮
    arrow_1.addEventListener('click', function () {
        if (flag) {
            flag = false;
            //如果走到了最后复制的一张  此时 我们的ul要快速复原  
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * width + 'px';
            }
            num--;
            animate(ul, -num * width, () => {
                flag = true;
            });
            //点击右侧按钮 小圆圈跟随一起变化 可以再声明一个控制小圆圈播放的变量
            circle--;
            circle = circle < 0 ? ol.children.length - 1 : circle;
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].style.backgroundColor = '';
            }
            //留下当前的小圆圈的
            ol.children[circle].style.backgroundColor = 'darkorange';
        }
    })

    //自动播放
    var timer = setInterval(() => {
        //手动调用点击事件
        arrow_2.click();
    }, 2000);
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值