zoukankan      html  css  js  c++  java
  • 一个封装函数的实现过程

    目标:封装一个函数,调用这个函数可以使任意的元素左右移动到任意的位置

    1.准备工作

    新知识点:用元素.style.属性只能获取标签内用style = "属性名:属性值;"里设置的属性,不能获取在头部的style标签中设置的属性

    用DOM元素的一个方法可以获取任意方式设置的属性:对象.offsetLeft可以获取left属性值,其他的还有element.offsetTop、element.offsetHeight、element.offsetWidth等,这个案例中使用element.offsetLeft获取盒子的向右偏移量,注意别忘了设置目标元素的position

    CSS部分

    <style>
         *{
             margin: 0;
             padding: 0;    
         }
            #dv{
                 100px;
                height: 100px;
                margin-top: 10px;
                background-color: pink;
                position: absolute;    
            }
        </style>

    HTML部分

    <input type="button" value="移动到400" id="btn1">
        <input type="button" value="移动到800" id="btn2">
        <div id="dv"></div>

    2.利用事件函数实现最基础的移动-版本1

    <script>
        var btn1 = document.getElementById("btn1");
        var btn2 = document.getElementById("btn2");
        var dv = document.getElementById("dv");
    
        function f1(){        //第一个的事件函数
                    var current = dv.offsetLeft;
                    setInterval(function(){
                        if (current < 400) {
                            current += 10;
                            dv.style.left = current +"px";
                        }    
                    },10);
                }
    
                function f2(){        //第二个的事件函数
                    var current = dv.offsetLeft;
                    setInterval(function(){
                        if (current < 800) {
                            current += 10;
                            dv.style.left = current +"px";
                        }    
                    },10);
                }
    
    
        btn1.addEventListener("click",function(){f1();},false);
        btn2.addEventListener("click",function(){f2();},false);
    
        </script>

    观察f1,f2,只有内部if里的参数不同,可以引入目标位值参数将f1,f2变为一个函数
    如何实现往回走呢?
    关键在于if里的东西:判断当前位置和目标位置的关系,当前位置<目标位值则要位置往前,当前位置>目标位值,则要位置往后

    3.修改后的版本2-可以实现来回移动

       <script>
        var btn1 = document.getElementById("btn1");
        var btn2 = document.getElementById("btn2");
        var dv = document.getElementById("dv");
        function ff(target){
                    var current = dv.offsetLeft;
                    
                    var timeId = setInterval(function(){
                        // if (current < target) {      //正走
                        //  current += 10;
                        //  dv.style.left = current +"px";  
                        // }else if(current > target){
                        //  current -= 10;      //反走
                        //  dv.style.left = current +"px"; 
                        // }else{
                        //  clearInterval(timeId);  //到达目的地清理定时器
                        // }    
                        //优化上述代码如下,添加一个变量temp可以设置每次走得距离
                        
                        if (current != target) {
                            var temp = 10;  //设置每次走的距离  这句代码放进计时器中才能实现往回走,即current>target的情况。因为这种情况每次计时都要设置temp = -10,不放进来的话temp会10,-10来回变,导致盒子抖动不能到达目标地
                        temp = current <= target ? temp : -temp;    
                            current += temp;
                            dv.style.left = current + "px";
                        }   
                        else{   //到达目的地清理定时器
                            clearInterval(timeId);
                        }
                    },10);
        }
    
        btn1.addEventListener("click",function(){ff(400);},false);
        btn2.addEventListener("click",function(){ff(800);},false);
    
        </script>

    注意应及时清理定时器以释放内存空间和避免造成其他BUG。优化代码引入了一个新的变量,这个变量的值甚至也可以由用户指定(在形参列表中多加一个形参),每次走得距离和定时器的间隔共同形成了一帧一帧的画面,实现了动画移动的效果。

    版本2出现BUG:如果设置的每次走得距离不能被400/800整除的话,会出现无法到达目的地而来回抖动的情况,而且无法实现清理定时器,在点击下一个按钮时会有多个定时器事件叠加发生,情况更复杂如:

        <script>
        var btn1 = document.getElementById("btn1");
        var btn2 = document.getElementById("btn2");
        var dv = document.getElementById("dv");
        function ff(target){
               var current = dv.offsetLeft;
                    
                    var timeId = setInterval(function(){
                        if (current != target) {
                            var temp = 90;  //设置每次走的距离  这里为了节约时间设置成了较大的距离
                        temp = current <= target ? temp : -temp;    
                            current += temp;
                            dv.style.left = current + "px";
                        }   
                        else{   //到达目的地清理定时器
                            clearInterval(tiemId);
                        }
                    },1000);    //这里为了方便分析将间隔变大以看出每次定时器触发后的结果,当然也可以利用控制台设置断点分析
        }
    
        btn1.addEventListener("click",function(){ff(400);},false);
        btn2.addEventListener("click",function(){ff(800);},false);
    
        </script>

    4.版本3:解决上述BUG

     <script>
        var btn1 = document.getElementById("btn1");
        var btn2 = document.getElementById("btn2");
        var dv = document.getElementById("dv");
        function ff(target){
                    clearInterval(timeId);  //解决隐藏的BUG,每次点击先清理定时器再创建定时器,解决多次点击时运动变快的BUG
                    var current = dv.offsetLeft;
                    var timeId = setInterval(function(){
                        if (current != target) {
                            var temp = 9;   //设置每次走的距离  
                            temp = current <= target ? temp : -temp;
                            if (Math.abs(current-target) > Math.abs(temp)) {    //当前距离大于每次走得距离则继续走
                                current += temp;
                                dv.style.left = current + "px";
                            } else {        //当前距离小于等于每次走得距离:则直接跳到目标位置,并且清理定时器
                                dv.style.left = target + "px";
                                clearInterval(timeId);
                            }   
                        }   
                        
                    },10);
                }
    
        btn1.addEventListener("click",function(){ff(400);},false);
        btn2.addEventListener("click",function(){ff(800);},false);
    
        </script>

    5.版本4最终版本,如果将目标元素作为函数的参数,则实现操纵任意元素的目的,注意要给目标元素添加position

    function move(element,target){
                clearInterval(timeId);    //解决隐藏的BUG,每次点击先清理定时器再创建定时器,解决多次点击时运动变快的BUG
                var current = element.offsetLeft;
                var timeId = setInterval(function(){
                    if (current != target) {
                        var temp = 9;    //设置每次走的距离    这句代码放进计时器中才能实现往回走,即current>target的情况。因为这种情况每次计时都要设置temp = -10,不放进来的话temp会10,-10来回变,导致盒子抖动不能到达目标地
                        temp = current <= target ? temp : -temp;
                        if (Math.abs(current-target) > Math.abs(temp)) {    //当前距离大于每次走得距离则继续走
                            current += temp;
                            element.style.left = current + "px";
                        } else {        //当前距离小于等于每次走得距离:则直接跳到目标位置,并且清理定时器
                            element.style.left = target + "px";
                            clearInterval(timeId);
                        }    
                    }    
                    
                },10);
            }
    
            btn1.addEventListener("click",function(){move(dv,400);},false);
            btn2.addEventListener("click",function(){move(dv,800);},false);

    通过封装一个函数,得到很多启发,封装函数-完成同一类事件可以多次调用--哪些东西需要作为参数传入-如何一步步实现目的-如何分析BUG解决BUG-如何优化函数

  • 相关阅读:
    lmdb简介——结合MVCC的B+树嵌入式数据库
    influxdb和boltDB简介——MVCC+B+树,Go写成,Bolt类似于LMDB,这个被认为是在现代kye/value存储中最好的,influxdb后端存储有LevelDB换成了BoltDB
    时序列数据库选型
    VoltDB介绍——本质:数据保存在内存,充分利用CPU,单线程去锁,底层数据结构未知
    关于时间序列数据库的思考——(1)运用hash文件(例如:RRD,Whisper) (2)运用LSM树来备份(例如:LevelDB,RocksDB,Cassandra) (3)运用B-树排序和k/v存储(例如:BoltDB,LMDB)
    241. Different Ways to Add Parentheses——本质:DFS
    麦克风阵列技术入门(3)
    [LeetCode]Palindrome Partitioning 找出所有可能的组合回文
    Linux在简短而经常使用的命令
    数据结构c字符串操作语言版本
  • 原文地址:https://www.cnblogs.com/yucheng6/p/9678470.html
Copyright © 2011-2022 走看看