前端 JavaScript -- 定时器及其应用(切换图片、动画效果实现、轮播图)

提示: 本篇文章过长,原本打算将文章分成三篇,但由于知识点都是相关串联的,考虑了一下还是决定放在一起,设置了目录 供大家选择性阅读

主要进行定时器的介绍简单使用,主要利用定时器实现动画效果,让图形变化更符合人的视觉要求,在最后利用定时器实现了轮播图功能。具体的功能实现以及注释都在代码中这里我就不再进行赘述。

定时器、延时器简介

主要介绍如何构建一个定时器
定时器:见名知意,根据设定的时间不断的回调函数(单位为毫秒 3000 = 3s)

注:如果定时器不进行关闭,则会一直执行下去,使用完毕一定要关闭定时器

注:定时器并不一定准确无误的定时执行 不是真正的定时,会存在一定的延时,如果延时较小对我们影响不大,但有些延时较大这样我们就接受不了了。
*为什么定时器不准确? 因为js是单线程运行的,定时器在主线程中运行,定时器中回调函数的执行必须是在运行栈中所有的代码都执行完毕后,才能调用回调函数。

主要应用的场景:倒计时功能 如手机发送验证码60s倒计时(在后期我发布的springboot项目中会涉及到,这里就不赘述了)、图片自动切换、动画效果的实现、轮播图等等 后面都有具体的代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> 定时器</title>
    <script>
        window.onload = function () {

            let num = document.getElementById("num");
            /**
             * setInterval()
             * - 定时调用,可以将一个函数,每隔一段时间调用一次
             * - 参数:1.回调函数,该函数每隔一段时间就调用一次
             *        2.调用间隔的时间,毫秒  1000 = 1s
             * - 返回值,返回一个Number类型的数据
             *          这个数字作为定时器的唯一标识
             *
             * clearInterval()  关闭一个定时器,方法中需要一个定时器的标识来关闭定时器
             */
            let count = 0;
            let timer = setInterval(function () {
                count++;
                num.innerHTML = count;
                //定时关闭
                if (count  == 10 ){
                    clearInterval(timer);
                }
            },1000)
        };
    </script>
</head>
<body>
 <h1 id="num"></h1>
</body>
</html>

既然有定时器,当然也有延时器,并且延时器和定时器之间可以相互转换,如设置一个定时器30s后执行一次,完全可以写一个30s后执行的延时器 效果相同,还省去了关闭定时器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>延时</title>
    <script>
        window.onload = function () {

            let num = document.getElementById("num");
            /**
             * 延时调用
             *  - 延时调用一个函数不马上执行,而是隔一段时间再执行,而且只会执行一次
             *  参数 1. 延时调用的方法
             *      2. 延时的时间 单位毫秒
             *
             * 注意:延时调用和定时调用可以相互代替,根据情况进行选择
             */
            let count = 0;
            let timer = setTimeout(function () {
                console.log(count);
            },1000)
            //取消延时调用
            clearTimeout(timer)
        };
    </script>
</head>
<body>
 <h1 id="num"></h1>
</body>
</html>

点击按钮实现图片自动切换

注:一定要看清楚自己图片保存的路径,我是保存全部放在img文件夹下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>切换图片</title>
    <script>
        window.onload =  function () {
            /**
             * 实现点击按钮切换图片功能
             */
            /**
             * imgArr 保存图片的集合
             * index 图片的索引信息
             * timer 保存定时器
             */
            let imgArr = ["img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg"];
            let index = 0;
            let timer;
            let btn1 = document.getElementById("btn1");
            let btn2 = document.getElementById("btn2");
            let img1 = document.getElementById("img1");
            //点击开始,定时切换图片
            btn1.onclick = function () {
                /**
                 * 点击一次开始按钮,就会开启一个定时器
                 * 如果点击多次,就会开启多个定时器,只有关闭开启的最后一个定时器时才会停止图片的切换
                 *
                 *注:在开启一个定时器之前我们需要将当前元素的上一个定时器关闭,这样存在的一直都是一个定时器,
                 * 而不会同时存在多个定时器
                 */
                //关闭定时器
                clearInterval(timer);
                //开启定时器,自动切换图片
                timer = setInterval(function () {
                        //索引自增
                        index++;
                        //判断是否超出最大索引,超出最大索引后为取余 从0开始
                        index = index % imgArr.length;
                        //修改img1的src属性,切换图片
                        img1.src = imgArr[index];
                },1000)

            };
            //点击按钮2 结束按钮 定时器停止
            btn2.onclick = function () {
                clearInterval(timer);
            };




        };
    </script>
</head>
<body>
      <img src="img/1.jpg" alt="" id="img1">
      <button id="btn1">开始</button>
      <button id="btn2">结束</button>
</body>
</html>

动画效果的实现

动画效果的实现:将一个元素块从屏幕左侧滑动到指定位置,或者控制元素块滑动后实现放大缩小等功能,下面的代码主要实现元素的上下左右滑动以及实现元素的高度 宽度变化,如果有其它的需求也可以自行修改元素的 style.属性

注:这里使用 left top进行元素的上下左右移动控制 通过修改函数参数中的target和style值控制
元素的高度宽度通过width height 进行控制 target 为目标执行的预期宽/高度

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <style>
        #box1{
            width: 100px;
            height: 100px;
            left: 0;
            background-color: red;
            position: absolute;
        }
    </style>
    <script>
        /**
         * 我使用的ES6 支持let 注意兼容性
         * ES6 以下 使用var
         * */

        window.onload = function () {
            let btn = document.getElementById("btn1");
            let box = document.getElementById("box1");
            //回调函数可以嵌套执行
            btn.onclick = function () {
                //console.log("点了")
                move(box,800,10,"left",function () {
                    move(box,300,10,"width",function () {
                        console.log("调用回调函数")
                    });
                });
            }
            /**
             * obj 执行动画对象
             * target 动画的目标位置
             * speed 执行速度
             * style 执行动画样式
             *      left top 移动方向
             *      width height  宽度高度变化
             * callback 回调函数,将会在动画执行完毕以后执行,拼接成多种动画效果
             * */
            function move(obj,target,speed,style,callback) {
            //关闭上一个定时器
                clearInterval(obj.timer);
                //获取元素目前位置
                //注:通过getStyle获取的数据不是纯数值,后面有跟着px,需要使用parseInt去获取有效的数值 然后对数值进行操作
                let current = parseInt(getStyle(obj,style));
                //判断速度正负,如果从0向右移动 为正,否则为负
                //如果当前位置超过给定目标位置,说明目标位置在左侧,需要向左移动为负;当前位置在目标左侧 向右移动 符号不变
                if (current > target){
                    speed = -speed;
                }
                //开启一个定时器,执行动画效果
                //向执行动画的对象中添加一个timer属性 用来保存自己的定时器标识
                obj.timer = setInterval(function () {
                        //获取box1原来的属性值
                    let oldValue = parseInt(getStyle(obj,style));
                    //在旧值得基础上增加
                    let newValue = oldValue + speed;

                    //判断新值是否超过target 与目标位置对齐消除误差
                    if ((speed < 0 && newValue < target)  || (speed > 0 && newValue > target)){
                        newValue = target;
                    };
                    //新值赋给元素
                    obj.style[style] = newValue + "px";
                    //当元素移动到目标位置,停止动画  向左移动
                    if (newValue == target){
                        clearInterval(obj.timer);
                        //动画执行完毕,调用回调方法
                        //判断,有回调函数调用没有则不调用
                        callback && callback();

                    }
                },30);

            }




            /**
             * 自定义函数,用来获取指定元素的当前样式
             *  obj : 指定元素
             *  name :获取样式名称
             */
            function getStyle(obj,name) {
                 //正常浏览器获取指定元素样式方法
                if (window.getComputedStyle){
                    return getComputedStyle(obj,null)[name];
                }else {
                    //IE8浏览器获取指定元素样式方法
                    return obj.currentStyle[name];
                }
            }
        };
    </script>
</head>
<body>
<button id="btn1">点击开始动画</button>
<div id="box1"></div>
</body>
</html>

轮播图

这是对上面的案例进行的综合,也是我们在设计网页时最常用的,关键的位置我都进行了大量的注释说明,方便大家进行理解。

功能:图片的自动切换2s切换一张 通过函数auto实现、点击导航栏 会切换到对应的图片,2s后从当前图片再实现图片的自动切换,如果不需要自动切换 注释掉auto函数即可

一定要注意自己图片的保存位置(路径不能出错),以及是否设置position属性
具体的详细内容,跟着代码理解即可,现在IE8基本不再使用,很多兼容IE8兼容没做,如果有需求,可以百度查询 没做的兼容,在注释中我都已经提示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #outdiv{
            width: 520px;
            height: 400px;
            margin: 40px auto;
            background-color: aquamarine;
            /*当我们对子元素开启绝对定位时,要对父元素开启一个相对定位*/
            position: relative;
            left: 0;
            /*超出窗口隐藏*/
            overflow: hidden;
        }
    /*     去掉默认的黑点*/
        #imgList{
            list-style: none;
            position: absolute;
            /*left: -520px;*/
        }
    /*    修改li的样式,横向排列*/
        #imgList li{
            float: left;
            margin: 0 10px;
        }
        /*开启导航栏绝对定位*/
        #navDiv{
            position: absolute;

        /*    设置导航的位置*/
            bottom: 30px;
        }
        #navDiv a{
        /*    转换为块元素*/
            display: block;
            float: left;

            margin: 0 5px;
            /*透明效果*/
            opacity: 0.6;
            /*IE8不兼容上面的透明样式,开启IE8的透明*/
            filter: alpha(opacity=60);
            width: 15px;
            height: 15px;
            background-color: red;
        }
        #navDiv a:hover{
            background-color: white;
        }
    </style>
    <script>
        window.onload = function () {
            //设置outdiv的宽度 根据li个数自动设置
            let imgList = document.getElementById("imgList");
            let imgArr = document.getElementsByTagName("img");
            //console.log(imgArr.length);
            imgList.style.width = 520 * imgArr.length + "px";

            //    导航按钮居中设置 根据元素个数自动设置
            //outDiv 520px 一个导航按钮15px 左右边距10px (520 - 25*按钮个数)/2
            let outdiv = document.getElementById("outdiv");
            let navDiv = document.getElementById("navDiv");
            //设置nav的偏移量 left  offsetWidth=水平方向 width + 左右padding + 左右border
            navDiv.style.left = (outdiv.offsetWidth - navDiv.offsetWidth) / 2 + "px";

            //    设置导航的鼠标浮动效果
            let aArr = document.getElementsByTagName("a");
            //      默认显示索引
            let index = 0;
            //自动切换动画定时器
            let  timer;
            /**
             * 点击超链接 实现图片的切换
             */
            for (let i = 0; i < aArr.length; i++) {
                // 为每一个超链接添加一个index属性
                aArr[i].index = i;
                aArr[i].onclick = function () {
                    //点击事件优先,当点击事件发生时,停止自动切换图片的定时器事件
                    clearInterval(timer);

                    //i在chrome中返回的是i的值即点击的按钮的对应的i  IE中返回的是i循环的总次数
                    //点击获取超链接的索引
                    index = this.index;
                    //切换图片 left = index * -520
                    // imgList.style.left = index * (-520) + "px"; 采用动画效果切换
                    //导航栏跟随图片改变
                    changeA();
                    //实现动画效果
                    move(imgList, -520 * index, 10,"left", function () {
                        //点击事件动画执行完毕后,开启自动切换图片事件
                        auto();
                    });
                    return false;
                };

            }
            //开启自动切换图片
            auto();

            //切换导航栏按钮
            function changeA() {
                //判断当前图片是否为最后一张图片
                if (index >= imgArr.length - 1 )
                {
                    //为最后一张图片时,下一张的导航按钮从头开始
                    index = 0;
                    /**
                     * 当显示为最后一张图片时,我们在最后一张图片后再放一张第一张图片,
                     * 然后利用css将第一张替换到最后一张,这样就形成了循环的感觉
                     * 不会切换到最后一张后又利用动画效果从右向左切换到第一张 细节看起来更加完善
                     */
                    imgList.style.left = 0;
                }

                //导航栏按钮点击变色,当点击下一个时上一个恢复原色
                //没有被选中的按钮都是css样式设计的颜色红色 style修改的为内联样式,优先级高
                for (let j = 0; j < aArr.length; j++) {
                    aArr[j].style.backgroundColor = "";
                }//点击时白色
                aArr[index].style.backgroundColor = "white";
            }

            //自动切换图片
            function auto() {
                // 开启一个定时器,定时切换图片
               timer =  setInterval(function () {
                    //索引自增
                    index++;
                    //超过最大值变为第一个
                    index = index % imgArr.length;
                    //切换图片
                    move(imgList, -520*index, 20, "left", function () {
                        changeA();
                    });
                },2000);
            }

            function move(obj,target,speed,style,callback) {
                //关闭上一个定时器
                clearInterval(obj.timer);
                //获取元素目前位置
                //注:通过getStyle获取的数据不是纯数值,后面有跟着px,需要使用parseInt去获取有效的数值 然后对数值进行操作
                let current = parseInt(getStyle(obj,style));
                //判断速度正负,如果从0向右移动 为正,否则为负
                //如果当前位置超过给定目标位置,说明目标位置在左侧,需要向左移动为负;当前位置在目标左侧 向右移动 符号不变
                if (current > target){
                    speed = -speed;
                }
                //开启一个定时器,执行动画效果
                //向执行动画的对象中添加一个timer属性 用来保存自己的定时器标识
                obj.timer = setInterval(function () {
                    //获取box1原来的属性值
                    let oldValue = parseInt(getStyle(obj,style));
                    //在旧值得基础上增加
                    let newValue = oldValue + speed;

                    //判断新值是否超过target 与目标位置对齐消除误差
                    if ((speed < 0 && newValue < target)  || (speed > 0 && newValue > target)){
                        newValue = target;
                    }
                    //新值赋给元素
                    obj.style[style] = newValue + "px";
                    //当元素移动到目标位置,停止动画  向左移动
                    if (newValue == target){
                        clearInterval(obj.timer);
                        //动画执行完毕,调用回调方法
                        //判断,有回调函数调用没有则不调用
                        callback && callback();

                    }
                },30);

            }

            function getStyle(obj,name) {
                //正常浏览器获取指定元素样式方法
                if (window.getComputedStyle){
                    return getComputedStyle(obj,null)[name];
                }else {
                    //IE8浏览器获取指定元素样式方法
                    return obj.currentStyle[name];
                }
            };
        }
    </script>
</head>
<body>
<!--创建一个大的盒子,作为外部容器-->
<div id="outdiv">
<!--    放置图片-->
    <ul id="imgList">
        <li><img src="img/1.jpg" alt=""></li>
        <li><img src="img/2.jpg" alt=""></li>
        <li><img src="img/3.jpg" alt=""></li>
        <li><img src="img/4.jpg" alt=""></li>
        <li><img src="img/1.jpg" alt=""></li>
    </ul>
<!--    导航-->
     <div id="navDiv">
         <a href=""></a>
         <a href=""></a>
         <a href=""></a>
         <a href=""></a>
     </div>
</div>
</body>
</html>

正在学习之中,不足之处感谢大家指正

感谢阅读 END

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值