原生js实现轮播图

原生js实现轮播图

1、原理

  1. 一个装图片的大盒子,显示器内水平垂直居中,溢出的部分不显示,并且设置为相对定位
  2. ul>li>img,n个li,ul的大小要比大盒子的大小大出n倍,所有以百分比计算,并且绝对定位
  3. li浮动
  4. 设置两个按钮和底下原点的位置
  5. 让ul自己动,然后改变其left的大小
  6. 当图片切换的时候会有一个逐渐变慢的过程,那么我们自己创建一个动画的函数
  7. 在最后一张图片后边克隆第一个图片节点,插入到最后一个位置,用于过渡
  8. 当点击左边,如果是第一张图片则将其过渡到最后一张克隆的图片
  9. 当点击右边,如果是最后一张图片,则过渡到第一张图片的位置
  10. 当我们不点击,则默认向右切换图片
  11. 其实重点就是ul的移动、移动这个逐渐变慢的过程、以及第一张和最后一张图片的过渡,只要掌握了这个基本上做这个是没有问题的

2、源码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>轮播图</title>
    <style>
        /* 清除浏览器自带的边距和不需要的样式 */
        
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            text-decoration: none;
        }
        /* 大盒子的样式 */
        
        .box {
            width: 500px;
            height: 300px;
            border: 1px solid #ccc;
            margin: 100px auto;
            padding: 5px;
        }
        /* 小盒子的样式 */
        
        .inner {
            width: 100%;
            height: 100%;
            /* 相对定位 */
            position: relative;
            /* 溢出的部分不显示 */
            overflow: hidden;
        }
        /* 图片的样式 */
        
        .inner img {
            /*图片的大小和小盒子的大小相同  */
            width: 500px;
            height: 300px;
            /* 图片居中对齐 */
            vertical-align: top;
        }
        /* 无序列表的样式 */
        
        .inner ul {
            width: 1000%;
            /* 绝对定位 */
            position: absolute;
            left: 0;
            top: 0;
        }
        /* li的属性 */
        
        .inner li {
            /* 左浮动 */
            float: left;
        }
        /* 有序列表的属性 */
        
        ol {
            position: absolute;
            height: 20px;
            right: 20px;
            bottom: 5px;
            text-align: center;
            padding: 5px;
        }
        
        ol li {
            display: inline-block;
            width: 20px;
            height: 20px;
            line-height: 20px;
            background-color: #fff;
            margin: 5px;
            cursor: pointer;
        }
        /* 第一个节点的背景颜色默认是红色 */
        
        ol li:first-child {
            background-color: red;
        }
        /* 箭头属性 */
        
        #arr {
            display: none;
        }
        
        #arr span {
            width: 40px;
            height: 40px;
            position: absolute;
            left: 5px;
            top: 50%;
            margin-top: -20px;
            background-color: #fff;
            cursor: pointer;
            text-align: center;
            font-weight: bold;
            font-family: "黑体";
            font-size: 30px;
            color: #000000;
            opacity: 0.5;
            border: 1px solid #ffffff;
            z-index: 999;
        }
        
        #arr #right {
            right: 5px;
            left: auto;
        }
        /* 鼠标经过里边的盒子则箭头出现 */
        
        .inner:hover #arr {
            display: block;
        }
    </style>
</head>

<body>
    <!-- 外边框大盒子 -->
    <div class="box">
        <!-- 装图片的盒子 -->
        <div class="inner">
            <!-- 无序列表装载的图片集合 -->
            <ul>
                <li>
                    <a href="javascript:;">
                        <img src="./images/1.jpg" alt="">
                    </a>
                </li>
                <li>
                    <a href="javascript:;">
                        <img src="./images/2.jpg" alt="">
                    </a>
                </li>
                <li>
                    <a href="javascript:;">
                        <img src="./images/3.jpg" alt="">
                    </a>
                </li>
                <li>
                    <a href="javascript:;">
                        <img src="./images/4.jpg" alt="">
                    </a>
                </li>
                <li>
                    <a href="javascript:;">
                        <img src="./images/5.jpg" alt="">
                    </a>
                </li>
            </ul>
            <!-- 有序列表装载的下方索引按钮 -->
            <ol class="bar">
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
                <li>5</li>
            </ol>
            <!-- 图片上的方向箭按钮 -->
            <div id="arr">
                <span id="left">
                    <
                </span>
                <span id="right">
                    >
                </span>
            </div>
        </div>
    </div>
    <script>
        window.onload = function() {
            // 准备工作:元素的获取
            // 获取左右按钮
            var left = document.querySelector("#arr #left");
            var right = document.querySelector("#arr #right");
            // 获取ul元素
            var ul = document.querySelector("ul");
            //获取ul下的所有li元素
            var liList = document.querySelector("ul").children;
            // 获取img元素的长度
            var imgWidth = document.querySelector("img").clientWidth;
            // 获取有序列表下的所有li
            var ol = document.querySelector(".bar");
            // 获取ol下的所有li节点
            var olli = ol.children;
            // 给ol中的每个li添加一个自定义属性
            for (var i = 0; i < olli.length; i++) {
                olli[i].setAttribute("index", i);
            };
            // 添加事件
            // 使用事件委托给ol添加点击事件
            ol.addEventListener("click", function(e) {

                // 判断:如果绑定事件的元素与事件的触发者一样,则为ol元素
                if (this == e.target) {
                    // 那么不执行
                    return;
                };
                // 调用设置颜色的函数
                setbackgroundColor(olli, e.target);
                // 获取触发该事件的元素对象的index属性
                var index = e.target.getAttribute("index");
                // 调用动画,默认向右
                animation(ul, -imgWidth * index)
            });

            // 深拷贝第一个节点
            var firstLi = liList[0].cloneNode(true);
            // 添加到ul中
            ul.append(firstLi);

            // 计数器
            var num = 0;
            // 存储计时器的id
            var time, timer = null;

            // 左边注册点击事件
            left.addEventListener("click", function() {
                // 当num到第一张图片的索引时
                if (num == 0) {
                    // 将num设置为最后一张图片的索引
                    num = liList.length - 1;
                    // 则此时改变ul距离左边的长度,其实就是切换到了最后一个图片的位置,从最后一个图片的位置往前过度
                    ul.style.left = num * -imgWidth + "px";
                };

                // 计数器递减
                num--;
                // 不断调用动画的函数
                animation(ul, -imgWidth * num);
                // 设置背景颜色
                setbackgroundColor(olli, num);
            });

            // 右边注册点击事件
            right.addEventListener("click", function() {
                // 当计数器到第六张图片的索引时,但是还没还得及进入动画的时候(原本为5张,但是我们还克隆了第一张)
                if (num == liList.length - 1) {
                    // 将num设置为第一张图片的索引
                    num = 0;
                    // 此时改变ul距离左边的距离,其实就是切换到第一张图片的位置,也就是从最后一张图片切换到第一张图片
                    ul.style.left = num + "px";
                };
                // 计数器递增
                num++;
                // 不断调用创建动画的函数
                animation(ul, -imgWidth * num);
                // 设置背景颜色
                setbackgroundColor(olli, num == liList.length - 1 ? 0 : num);
            });

            // 计时器自调用right的点击事件
            setInterval(function() {
                right.click();
            }, 2000)

            // 封装设置下方按钮背景颜色的函数
            function setbackgroundColor(olli, index) {
                // 遍历ol下所有的li元素
                for (var i = 0; i < olli.length; i++) {
                    // 先将所有背景颜色变白
                    olli[i].style.backgroundColor = "#fff";
                };
                // 目标元素改变背景颜色
                olli[index].style.backgroundColor = "red";
            };

            //封装的动画函数 ,并接收一个元素对象和目标位置参数
            function animation(obj, target, callback) {
                // 每次进入该函数之前都清除之前的计时器
                clearInterval(time);
                //创建计时器
                time = setInterval(function() {
                    // 获取left要走的长度,速度依次变慢
                    var step = (target - obj.offsetLeft) / 10;
                    // 如果每次的长度大于0则向上取整,否则向下取整
                    step = step > 0 ? Math.ceil(step) : Math.floor(step);
                    // 如果ul的left==目标点
                    if (target == obj.offsetLeft) {
                        // 则停止计时器
                        clearInterval(time);
                    };
                    // 设置ul的left
                    obj.style.left = obj.offsetLeft + step + "px";
                    // 如果callback存在,则调用
                    if (callback) {
                        callback();
                    };
                }, 20);
            };
        }
    </script>
</body>

</html>
      // 设置ul的left
                obj.style.left = obj.offsetLeft + step + "px";
                // 如果callback存在,则调用
                if (callback) {
                    callback();
                };
            }, 20);
        };
    }
</script>
```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

御弟謌謌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值