欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js定时器实现自动轮播图

程序员文章站 2024-03-22 00:02:28
...

自动轮播的效果图如下:
js定时器实现自动轮播图

<!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;
        }

        ul,
        ol {
            list-style: none;
        }

        a {
            text-decoration: none;
            color: #333;
        }

        .box {
            width: 300px;
            height: 300px;
            margin: 40px 300px;
            border: 2px solid blue;
            position: relative;
            overflow: hidden;
        }

        .clear::after {
            content: "";
            display: block;
            clear: both;
        }

        .box ul {
            height: 100%;
            font-size: 30px;
            /* 设置定位是因为后面复制li加到最前面时要显示的是第二张 */
            position: absolute;
            left: 0;
            top: 0;
        }

        .box ul li {
            width: 300px;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            float: left;
        }

        .box ol {
        	width: 100%;
            display: flex;
            justify-content: space-evenly;
            align-items: center;
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
        }

        .box ol li {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            border: 1px solid #000;
            margin: 0 15px;
            cursor: pointer;
        }

        .box ol li.active {
            background-color: rebeccapurple;
        }

        .box div {
            width: 100%;
            height: 50px;
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .box div a {
            font-size: 40px;
            color: #000;
            font-weight: bold;
        }
    </style>
</head>

<body>

    <div class="box">
        <ul class="clear">
            <li style="background: hotpink;">图片一</li>
            <li style="background: greenyellow;">图片二</li>
            <li style="background: rosybrown;">图片三</li>
            <li style="background: burlywood;">图片四</li>
            <li style="background: seagreen;">图片五</li>
            <!-- <li style="background: hotpink;">图片六</li>
            <li style="background: greenyellow;">图片七</li>
            <li style="background: rosybrown;">图片八</li>
            <li style="background: burlywood;">图片九</li>
            <li style="background: seagreen;">图片十</li> -->
        </ul>
        <ol></ol>
        <!-- 此处还没实现,有需要可以评论联系我一起讨论 -->
        <div>
            <a href="JavaScript:;"> &lt; </a>
            <a href="JavaScript:;"> &gt; </a>
        </div>
    </div>
    <script src="./utils.js"></script>
    <script>

        var oBox = document.querySelector(".box");

        var oUl = document.querySelector("ul");

        var oUllis = document.querySelectorAll("ul li");// 一开始的li的长度,不包括后面复制加入的两个li

        var oOl = document.querySelector("ol");

        var LiWidth = parseInt(window.getComputedStyle(oUllis[0]).width);// 获取图片的宽度

        var index = 1; // 显示当前图片的位置,用来计算移动多少

        var time = 0; // 保存自动播放中定时器编号,用于后面清除定时器

        // 动态生成小圆圈函数
        setLi();

        // 复制第一个图片和最后一个图片的函数
        copyLi();

        // 得到小圆圈,用于下面改变样式
        var oOllis = document.querySelectorAll("ol li");

        // 自动播放函数
        autoLoop();

        // 鼠标移上去停止移动,清除定时器,拿开就重新执行自动播放函数
        stopLoop();
        
    </script>
</body>

</html>

utils.js文件中代码如下:


/*
    1.动态生成点击用的圆圈li,因为多少图片不固定,所以需要根据图片数量动态生成

    2.形成轮播的视觉,复制最后一个放在第一位,然后复制第一个放在最后一位

    3.移动函数,设置目标位置,通过不断更新当前位置与目标位置作比较,到达就停止,
        也可以设置其他属性(例如宽)的目标值,变化完成就停止

    4.写个自动播放函数通过控制移动函数动作,移动函数有个参数是回调函数。

    5.回调函数,移动结束后会执行回调函数,用来在移动结束后瞬间回到第一张图片

    6.停止播放函数,用鼠标控制播放函数,移上去停止播放,移走鼠标后继续执行播放函数
 */

// 动态生成小圆圈函数
function setLi() {

    var str = "";

    oUllis.forEach(function (v, key) {

        if (key === 0) {

            str += `<li class='active'></li>`;
        }
        else {
            str += `<li></li>`;
        }

    });

    oOl.innerHTML = str;
}

// 复制第一个图片和最后一个图片的函数
function copyLi() {

    var liFirst = oUllis[0];

    var liLast = oUllis[oUllis.length - 1];

    // 先克隆第一个和最后一张图片,然后加入到ul中最前面和最后面 
    var first = liFirst.cloneNode(true);

    var last = liLast.cloneNode(true);

    oUl.appendChild(first);

    oUl.insertBefore(last, liFirst);

    // 设置ul宽度,使其不会换行排列
    oUl.style.width = ((oUllis.length + 2) * LiWidth) + "px";

    // 改变ul的初始位置,使其显示的是第一张图片
    oUl.style.left = -LiWidth + 'px';

}

// 传入的参数是标签对象和存放样式的一个对象,对象存储的是运动的目标值,最后是个回调函数
function move(elem, obj, callBack) {

    // 存储定时器编号
    let time = {};

    // 循环遍历对象,有几个键值对就创建几个不同的定时器用来执行不同的样式变化
    for (let type in obj) {

        let oldVal = 0;

        // 透明度是小数,先转换一下
        if (type === "opacity") {

            // 因为有小数,小数判断相等时有误差,下面的判断难以执行,所以特殊转换
            oldVal = parseFloat(window.getComputedStyle(elem)[type]) * 100;

        }
        else {

            oldVal = parseInt(window.getComputedStyle(elem)[type]);
        }

        // 对象的键值对分别代表样式属性和定时器标号
        time[type] = setInterval(function () {

            // 分五次运动到目标位置,分母数值越大运动越慢
            let val = (obj[type] - oldVal) / 10;

            // 设置取整,整数就向上取整,比如0.9直接取1,-0.9取-1,否则下面判断无法等于
            val = val > 0 ? Math.ceil(val) : Math.floor(val);

            // 更新位置
            oldVal += val;

            // console.log(oldVal);

            // 进行判断属性是不是透明度,因为给的是乘以100后的值,需要除以100,写入标签样式中
            if (type === "opacity") {

                elem.style[type] = oldVal / 100;
                // console.log(oldVal);

            }
            else {

                elem.style[type] = `${oldVal}px`;

            }

            if (oldVal == obj[type]) {

                clearInterval(time[type]);

                // delete 操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放
                delete (time[type]);

            }
            if (Object.keys(time) == 0) {

                // 运动停止后执行的函数
                callBack();

            }

        }, 100);
    }
}

// 自动播放函数
function autoLoop() {

    time = setInterval(function () {


        // 加一次就是需要加载下一张图片了
        index++;

        move(oUl, { left: -index * LiWidth }, moveEnd);

		// 因为小圆圈的数量比图片少一个,就是复制的那个,所以要先判断长度,否则会出错,
		// 因为最后一个对应的小圆圈是第一个,而不是减1,
        if (index == oOllis.length + 1) {

            oOllis[oOllis.length - 1].className = "";

            oOllis[0].className = "active";

        }
        else {

			// 因为index是从1开始,所以要减1,减2,清除上个标签的样式,给现在这个标签加上样式
            oOllis[index - 2].className = "";

            oOllis[index - 1].className = "active";

        }

    }, 4000); // 时间至少四秒,否则会出现闪烁,执行出问题

}

// 移动结束后要瞬间跑到第一张图片开始那
function moveEnd() {

    if (index == oUllis.length + 1) {

        index = 1;

        oUl.style.left = -index * LiWidth + 'px';
    }

}

// 鼠标移上去停止移动,清除定时器,拿开就重新执行自动播放函数
function stopLoop() {

    oBox.addEventListener("mouseover", function () {

        clearInterval(time);
    });

    oBox.addEventListener("mouseout", function () {

        autoLoop();
    });
}

此种方法写的自动轮播图大部分都是js自动生成,可扩展性强,随便加入图片可不用改变css样式。

有需要实现点击的轮播图可以参考js实现点击轮播图,有需要扩展的或者不懂的可以跟我一起讨论。

相关标签: 案例