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:;" name="left"> &lt; </a>
            <a href="JavaScript:;" name="right"> &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 oDiv = oBox.querySelector("div");// 找到oBox下的div
		
        var LiWidth = parseInt(window.getComputedStyle(oUllis[0]).width);// 获取图片的宽度

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

        var time = 0; // 保存自动播放中定时器编号,用于后面清除定时器
        
		var bool1 = true;  // 防止点击过快的变量

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

        // 复制第一个图片和最后一个图片的函数
        copyLi();
        
        // 自动播放函数
        autoLoop();

        // 鼠标移上去停止移动,清除定时器,拿开就重新执行自动播放函数
        stopLoop();
        
        // 页面缩小时执行的函数,防止页面隐藏时还在执行程序,进行切换
        hidden();
        
		// 左右点击切换
		leftRight();
		
		// 点击小圆圈
		focus();
    </script>
</body>

</html>

utils.js文件中代码如下:


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

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

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

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

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

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

	7.隐藏函数,页面隐藏时停止程序执行,不在切换

	8.左右点击函数,此处注意a链接中的href不能不写,否则无法执行js程序
	
	9.点击小圆圈函数,通过自己设置的index属性,找到对应的图片位置进行移动
 */

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

    var str = "";

    oUllis.forEach(function (v, key) {

        if (key === 0) {

            str += `<li index="${key + 1}" class='active'></li>`;
        }
        else {
            str += `<li index="${key + 1}"></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);

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

}

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

	// 移动结束后重新设置初始值
	bool1 = true;
    
    // 如果是最后一张要瞬间转到第二张
    if (index == oUllis.length + 1) {

        index = 1;

        oUl.style.left = -index * LiWidth + 'px';
    }
	
	//如果是第一张需要瞬间转到倒数第二张
   else if (index == 0) {

       index = oUllis.length;

       oUl.style.left = (-liWidth * index) + 'px';
   }

 	// 得到小圆圈,用于下面改变样式.先改变图片才会改变焦点,所以要放到最下面
    var oOllis = document.querySelectorAll("ol li");

	oOllis.forEach(function (val, key) {

        // 先清空所有
        val.className = "";

        // 再根据属性index进行点击样式添加
        if (val.getAttribute("index") == index) {

            val.className = "active";
        }
    });
}

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

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

        clearInterval(time);
    });

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

        autoLoop();
    });
}

// 解决页面最小化时,程序一直执行问题
// 通过判断浏览器是否在显示,来停止或执行,自动轮播
// visibilitychange   当页面显示状态改变时,执行的的程序
//    document.visibilityState   显示状态数据
//      如果显示 visible
//      如果隐藏 hidden
function hidden() {

    // 当页面显示状态发生改变时,触发事件,执行程序
    document.addEventListener('visibilitychange', function () {

        if (document.visibilityState === 'hidden') {

            // 如果显示状态是隐藏,停止定时器,不执行自动轮播
            clearInterval(time);
        }
        else if (document.visibilityState === 'visible') {
            
            // 如果是显示状态,就执行自动轮播函数
            autoLoop();
        }
    })
}

// 左右方向的点击
function leftRight() {

    oDiv.addEventListener("click", function (e) {

		// 事件兼容
        e = e || window.event;

		// 事件对象兼容
        e.target = e.target || e.srcElement;

		if (!bool1) {  // 判断是不是初始值,是就返回,不是就执行

            return;
        }

        bool1 = false;
        
        if (e.target.getAttribute("name") == "left") {

            index--;

        }
        else {

            index++;
        }

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

    })
}

// 点击小圆点
function focus() {

   oOl.addEventListener("click", function (e) {

       // 只有点击li才有效,空白部分没用
       if (e.target.tagName == "LI") {

           if (!bool1) { return; }

           bool1 = false;

           // 得到当前圆点的位置,正好对应图片位置
           index = e.target.getAttribute("index") * 1;

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

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

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值