• JS运动


    新学的JS运动,和各位分享一下。

    提到运动,肯定要对元素进行定位,通过更改它的left,top值来实现定位的目的,运动过程用定时器来实现。

    基本步骤:

      1.关闭上一个定时器(多次触发事件会开启多个定时器,会累加)

      2.开启一个定时器

      3.定义一个值作为运动的速度

      4.判断定时器什么时候关闭,也就是终止条件

      5.让元素怎样动

    下面开始说几种常见的运动

    1.匀速运动

    速度是不变的。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            *{margin:0;padding:0;}
            #box{
                 100px;
                height: 100px;
                background: red;
                position: absolute;
            }
        </style>
    </head>
    <body>
        <div id="box"></div>
    </body>
    </html>
    <script>
    var oBox = document.getElementById("box");
    var speed = 10;

    var timer=null;
    document.onclick = function  () {
       timer= setInterval(function(){

      if(oBox.offsetLeft>=400){

        clearInterval(timer);

      }else{

          oBox.style.left = oBox.offsetLeft+speed+"px";

      }
         
        },30)
    }
    </script>

    oBox会匀速向右运动400px后停止,建议终止条件写oBox.offsetLeft>=400,而不是oBox.offsetLeft==400,因为定时器每次加一个speed,不一定正好加到所给的终止值。

    以下案例的布局是一样的,所以只写JS代码

    2.减速运动

    <script>
    var oBox = document.getElementById("box");
    var speed = 40;
    var timer=null;
    document.onclick = function  () {
       timer= setInterval(function(){
        speed--;
        if(speed<0){
            speed=0;
        }
        console.log();
      if(oBox.offsetLeft>=800){

        clearInterval(timer);

      }else{

          oBox.style.left = oBox.offsetLeft+speed+"px";

      }
         
        },30)
    }
    </script>

    速度每次减减,加速度相同,所以是匀减速运动

    3.匀加速运动(同理)

    <script>
    var oBox = document.getElementById("box");
    var speed = 5;
    var timer=null;
    document.onclick = function  () {
       timer= setInterval(function(){
        speed++;
        if(speed>=40){
            speed=40;
        }
      if(oBox.offsetLeft>=800){

        clearInterval(timer);

      }else{

          oBox.style.left = oBox.offsetLeft+speed+"px";

      }
         
        },30)
    }
    </script>

    4.缓冲运动  (样式改变)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            *{margin:0;padding:0;}
            #box{
                 100px;
                height: 100px;
                background: red;
                position: absolute;
                left: 800px;
            }

            #border{
                 1px;
                height: 300px;
                background: #000;
                position: absolute;
                left: 400px;
                top: 0;
            }
        </style>
    </head>
    <body>
        <div id="box"></div>
        <div id="border"></div>
    </body>
    </html>

    <script>

    var oBox = document.getElementById("box");
    var timer = null;

    document.onclick=function(){
            clearInterval(timer);
            timer=setInterval(function(){
                var speed=(400-oBox.offsetLeft)/8;
                speed=speed>0?Math.ceil(speed):Math.floor(speed);
                console.log(speed);
                if(oBox.offsetLeft==400){
                    clearInterval(timer);
                }else{
                    oBox.style.left=oBox.offsetLeft+speed+"px";
                }
            },30);
        }

    </script>

    每次都把速度的值变小,但不是均匀的改变(跟减速运动最大不同),取整是为了让浏览器更好的计算,避免计算小数,以免出现误差。

    封装一下。

    function move(obj,iTarget){
        clearInterval(timer);
        timer = setInterval(function(){
            //速度
            var speed = (iTarget - obj.offsetLeft)/8;
            speed = speed>0?Math.ceil(speed):Math.floor(speed);

            if(obj.offsetLeft==iTarget){
                clearInterval(timer)
            }else{
                obj.style.left = obj.offsetLeft+speed+"px";
            }

        },30)
    }

    obj,是对象,iTarget是目标值。例如:move(div,400) 

    5.上面的封装不完善,想改变一个元素的透明度就做不到。透明度是小数且没单位,还得做IE的兼容,下面是怎样更改透明度

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            *{margin:0;padding:0;}
            #box{
                 100px;
                height: 100px;
                background: red;
                opacity: 1;
                filter: alpha(opacity: 100);

            }
        </style>
    </head>
    <body>
        <div id="box"></div>
    </body>
    </html>
    <script>
    var oBox = document.getElementById("box");
    var timer =null;
    var alpha = 100;

        document.onclick=function(){
            clearInterval(timer);
            timer=setInterval(function(){
                var speed=(30-alpha)/8;
                speed=speed>0?Math.ceil(speed):Math.floor(speed);
                if(alpha==30){
                    clearInterval(timer);
                }else{
                    alpha+=speed;
                    oBox.style.opacity=alpha/100;
                    oBox.style.filter="alpha(opacity:"+alpha+")";
                }
            },30);
        }
    </script>

    6.考虑到透明度,于是再次封装。

    这次先封装一个获取非行内元素

    function getStyle(obj,attr){

    return obj.currentStyle?obj.currentStyle[attr]:getComputedStyle(obj,false)[attr];

    }

    function move(obj,target,attr){
        clearInterval(timer);
        timer=setInterval(function(){
            var icur=0;
            if(attr=="opacity"){
                //避免opacity的值是0.5555555这样,所以取整
                icur=parseInt(getStyle(obj,attr)*100);
            }else{
                icur=parseInt(getStyle(obj,attr));
            }
            
            var speed=(target-icur)/8;
            speed=speed>0?Math.ceil(speed):Math.floor(speed);
            
            if(icur==target){
                clearInterval(timer);
            }else{
                if(attr=="opacity"){
                    obj.style.opacity=(icur+speed)/100;
                    obj.style.filter="alpha(opacity:"+(icur+speed)+")";
                }else{
                    obj.style[attr]=icur+speed+"px";
                }
            }
        },30);
    }

    oBox.onmouseover = function(){
        move(this,100,"opacity");
    }

    调用一下,没问题

    7.多物体运动框架

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            *{margin:0;padding:0;}
            div{
                 100px;
                height: 100px;
                background: red;
                opacity: 0.3;
                filter: alpha(opacity: 30);
                margin: 10px;
            }
        </style>
    </head>
    <body>
        <div></div>
        <div></div>
        <div></div>
    </body>
    </html>
    <script>
    function getStyle(obj,attr){
        if(obj.currentStyle){
            return obj.currentStyle[attr];
        }else{
            return getComputedStyle(obj,false)[attr];
        }
    }


    function move(obj,iTarget,attr){
        //obj.timer,定时器之间不影响
        clearInterval(obj.timer);
        obj.timer = setInterval(function(){
            //第一步 判断attr是否为透明度
            var iCur = 0;
            if(attr == "opacity"){
                iCur =parseInt(getStyle(obj,attr)*100);
            }else{
                iCur = parseInt(getStyle(obj,attr));
            }

            //第二步算速度
            var speed = (iTarget - iCur )/8;
            speed = speed>0?Math.ceil(speed):Math.floor(speed);


            //第三步
            if(iCur == iTarget){
                clearInterval(obj.timer);
            }else{
                if(attr == "opacity"){
                    obj.style.opacity = (iCur+speed)/100;
                    obj.style.filter = "alpha(opacity:"+(iCur+speed)+")";
                }else{
                    obj.style[attr] = iCur+speed+"px";
                }

            }


        },30)
    }

    var aDiv = document.getElementsByTagName("div");

    aDiv[0].onmouseover = function(){
        move(this,300,"width")
        
    }

    aDiv[1].onmouseover = function(){
        move(this,300,"height")
    }

    aDiv[2].onmouseover = function(){
        move(this,100,"opacity")
    }
    </script>

    当多物体的时候,只用一个timer定义定时器时,会影响下一个物体的运动,所以要用obj.timer,关闭的时候关闭自己的定时器,不影响其他定时器的执行

    8.链式运动

    function getStyle(obj,attr){
        if(obj.currentStyle){
            return obj.currentStyle[attr];
        }else{
            return getComputedStyle(obj,false)[attr];
        }
    }


    function move(obj,iTarget,attr,fn){
        clearInterval(obj.timer);
        obj.timer = setInterval(function(){
            //第一步 判断attr是否为透明度
            var iCur = 0;
            if(attr == "opacity"){
                iCur =parseInt(getStyle(obj,attr)*100);
            }else{
                iCur = parseInt(getStyle(obj,attr));
            }

            //第二步算速度
            var speed = (iTarget - iCur )/8;
            speed = speed>0?Math.ceil(speed):Math.floor(speed);


            //第三步
            if(iCur == iTarget){
                clearInterval(obj.timer);
                fn&&fn();
            }else{
                if(attr == "opacity"){
                    obj.style.opacity = (iCur+speed)/100;
                    obj.style.filter = "alpha(opacity:"+(iCur+speed)+")";
                    
                }else{
                    obj.style[attr] = iCur+speed+"px";
                }

            }


        },30)
    }

    var aDiv = document.getElementsByTagName("div");

    aDiv[0].onmouseover = function(){
        move(this,100,"opacity",function(){
            move(aDiv[0],300,"height");
        })
        
    }
    //给2个move(),下面会覆盖上面的函数,再写一个事件,也不行
    aDiv[1].onmouseover = function(){
        move(this,300,"height")
    }

    aDiv[2].onmouseover = function(){
        move(this,100,"opacity")
    }

    给原来封装的函数加一个回调函数,解决

    9.完美运动(让元素2个属性同时运动,链式运动只能一个执行完,再执行另一个)

    <script>
    function getStyle(obj,attr){
        if(obj.currentStyle){
            return obj.currentStyle[attr];
        }else{
            return getComputedStyle(obj,false)[attr];
        }
    }
    //obj={100,height:200}

    function move(obj,json,fn){
        //防止多次点击   关闭掉上一个定时器
        clearInterval(obj.timer);
        //开启定时器  obj.timer:防止多个对象抢定时器
        obj.timer = setInterval(function(){
            //开关门
            var bStop = true;
            //传入的是一个对象 需要将对象中所有的值进行遍历
            for(var attr in json){
                /*
                    因为offset的局限性太大,如果想要这个方法灵活多用只能用获取非行间样式

                    考虑2点
                        1、透明度是小数 不能够直接取整需要先*100在取整

                        2、因为getStyle()获取出来的是字符串 我们需要将它转换为数字
                 */
                var iCur = 0;
                if(attr == "opacity"){
                    iCur = parseInt(getStyle(obj,attr)*100);
                }else{
                    iCur = parseInt(getStyle(obj,attr));
                }



                /*
                因为要做缓存运动,因此需要计算速度 速度是一个不定值  
                公式:  (目标值 - 当前对象的位置) /系数  建议是8

                考虑的问题:
                    计算机处理小数有问题因此需要将小数干掉,我们要进行向上取整和向下取整
                 */
                //算速度
                var speed = (json[attr] - iCur)/8;
                speed = speed>0?Math.ceil(speed):Math.floor(speed);

                /*判断是否都已经到达终点 只要有一个没有到达终点就将bStop为false  循环完毕以后判断bstop来决定关闭定时器*/
                if(json[attr] !=iCur){
                    bStop = false;
                }


                /*
                    考虑2部分
                        1、透明度是不需要加px的因此需要单独判断
                        2、普通的属性是需要加px的因此需要再次判断

                 */
                if(attr == "opacity"){
                    //透明度的兼容性
                    obj.style.opacity = (iCur+speed)/100;
                    obj.style.filter = "alpha(opacity:"+(iCur+speed)+")";
                }else{
                    obj.style[attr] = (iCur+speed)+"px";
                }
                

            }

            //当循环完毕以后 判断bStop的状态来决定是否关闭定时器
            if(bStop){
                clearInterval(obj.timer);
                //链式操作
                fn&&fn();
            }

        },30)
    }

    var aDiv = document.getElementsByTagName("div");

    aDiv[0].onmouseover = function(){
        move(this,{300,height:150},function(){
            move(aDiv[0],{opacity:100});
        });
    }

  • 相关阅读:
    【代码笔记】iOS-书架页面
    iOS-@inerface的11条规范写法
    (转)iOS-蓝牙学习资源博文收集
    iOS App启动图不显示的解决办法.
    理解点击屏幕的事件响应--->对- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法的理解
    理解点击屏幕的事件响应--->对UIView的hitTest: withEvent: 方法的理解
    iOS GCD中级篇
    iOS开发UI篇—自定义layer
    iOS开发UI篇—CALayer
    iOS-绘制图层-CALayer的属性
  • 原文地址:https://www.cnblogs.com/lzn0330/p/9538903.html
Copyright © 2020-2023  润新知