javascrip运动原理

js运动
1.匀速运动

    <style type="text/css">
        div {
            width: 100px;
            height: 100px;
            background: orange;
            position: absolute;
            left: 0px;
            top: 0px;
        }
        button {
            margin-top: 150px;
        }
        span {
            position: absolute;
            left: 300px;
            top: 0px;
            width: 1px;
            height: 100px;
            background: black;
        } 
    </style>
</head>
<body>
    <div></div>
    <span></span>
    <button id="btn">run</button>
    <script>
     var oDiv = document.getElementsByTagName('div')[0];
     var oBtn = document.getElementById('btn');
     var timer = null;
        oBtn.onclick = function () {
             // s = vt t s
             startMove(oDiv , 300);//让谁运动,运动到哪里
         }
         
         function startMove (dom, target) {
             clearInterval(timer);
            var iSpeed = target - dom.offsetLeft> 0 ? 7 : -7;
             timer = setInterval(function () {
                 if (Math.abs(target-dom.offsetLeft) < Math.abs(iSpeed)) {
                    clearInterval(timer);
                    dom.style.left = target+'px';
                 }else {
                     dom.style.left = dom.offsetLeft + iSpeed + 'px';
                 }
             }, 30);
         }
</script>

2.缓冲运动

 <style type="text/css">
        div {
            width: 100px;
            height: 100px;
            background: orange;
            position: absolute;
            left: 0px;
            top: 0px;
        }
        button {
            margin-top: 150px;
        }
        span {
            position: absolute;
            left: 300px;
            top: 0px;
            width: 1px;
            height: 100px;
            background: black;
        } 
    </style>
</head>
<body>
    <div></div>
    <span></span>
    <button id="btn">run</button>
    <script>
     var oDiv = document.getElementsByTagName('div')[0];
     var oBtn = document.getElementById('btn');
     var timer = null;
        oBtn.onclick = function () {
             // s = vt t s
             startMove(oDiv , 300);//让谁运动,运动到哪里
         }
        // 物体的速度 距离目标点越近 就越小 当到达目标点时 速度减小为0
         function startMove (dom, target) {
             clearInterval(timer);
            var iSpeed = null;
             timer = setInterval(function () {
                iSpeed = (target - oDiv.offsetLeft) / 7;

                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);//像素原因
                if(oDiv.offsetLeft == target){
                    clearInterval(timer);
                   
                 }else {
                    oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
                 }
             }, 30);
         }
</script>

类似电脑清楚缓存球的动态

    <style type="text/css">
    .wrapper {
            width: 400px;
            height: 80px;
            background: orange;
            position: absolute;
            left: -400px;
            top: 200px;
        }
        .wrapper span {
            width: 50px;
            height: 80px;
            background: red;
            position: absolute;
            right: -50px;
            top: 0px;
        } 
    </style>
</head>
<body>
    <div class="wrapper">
        <span></span>
    </div>
   
  
   
   
    <script> 
    var oDiv = document.getElementsByClassName('wrapper')[0];
    timer=null;
        oDiv.onmouseenter = function () {
            startMove(this, 0);
         }
         oDiv.onmouseleave = function () {
             startMove(this, -400);
         }
            function startMove (dom, target) {
             clearInterval(timer);
            var iSpeed = null;
             timer = setInterval(function () {
                iSpeed = (target - oDiv.offsetLeft) / 7;

                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);//像素原因
                if(oDiv.offsetLeft == target){
                    clearInterval(timer);
                   
                 }else {
                    oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
                 }
             }, 30);
         }
    
    
     </script>
    

透明度渐变缓存
    <style type="text/css">
    div {
            width: 100px;
            height: 100px;
            background: red;
            opacity: 1;
        }
    </style>
</head>
<body>
  <div>

  </div>
   
  
   
   
    <script> 
   
    var timer = null;
    var oDiv=document.getElementsByTagName('div')[0];
    //获取样式精准的值
    oDiv.onclick=function (){
        startMove(this , 0.5);
    }
    function getStyle (dom, attr) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(dom, null)[attr];
            }else {
                return dom.currentStyle[attr];
            }
        }
   
          function startMove (dom, target) {
             clearInterval(dom.timer);
             var iSpeed = null, iCur = null;
             dom.timer = setInterval(function () {
                 iCur = parseFloat( getStyle(dom, 'opacity') ) * 100;
                 iSpeed = ( target - iCur ) / 7;
                 // .... 
                 iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                 if (iCur == target) {
                     clearInterval(dom.timer);
               }else {
                     dom.style.opacity = (iCur + iSpeed)/100;
                 }
        }, 30);
     }       
    
 </script>

3.多物体运动

 <style type="text/css">
    div {
            width: 100px;
            height: 100px;
            background: red;
            margin-bottom: 100px;
        }
       
    </style>
</head>
<body>
  <div></div>
  <div></div> 
  <div></div>
  <div></div>
   
    <script> 
   
    var timer = null;
    var oDivArray = document.getElementsByTagName('div');

    for (var i = 0; i < oDivArray.length; i++) {
            oDivArray[i].onmouseenter = function () {
                startMove(this, 400);
             }
             oDivArray[i].onmouseleave = function () {
                 startMove(this, 100);
             }
         }
    //获取样式精准的值
    // oDiv.οnclick=function (){
    //     startMove(this , 0.5);
    // }
    function getStyle (dom, attr) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(dom, null)[attr];
            }else {
                return dom.currentStyle[attr];
            }
        }
   
          function startMove (dom, target) {
             clearInterval(dom.timer);
             var iSpeed = null, iCur = null;
             dom.timer = setInterval(function () {
                 iCur = parseFloat( getStyle(dom, 'width') ) ;
                 iSpeed = ( target - iCur ) / 7;
                 // .... 
                 iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                 if (iCur == target) {
                     clearInterval(dom.timer);
               }else {
                     dom.style.width  = iCur + iSpeed + 'px';
                 }
        }, 30);
     }       
    
     </script>

物体不同运动

    <style type="text/css">
    div {
            width: 100px;
            height: 100px;
            background: red;
            margin-bottom: 100px;
            border: 5px solid  black;
        }
       
    </style>
</head>
<body>
  <div></div>
  <div></div> 
  <div></div>
  <div></div>
   
    <script> 
   
    var timer = null;
    var oDivArray = document.getElementsByTagName('div');

        oDivArray[0].onclick = function () {
            startMove(this, 'width', 400);
        }

        oDivArray[1].onclick = function () {
            startMove(this, 'height', 400);
        }
        oDivArray[2].onclick = function () {
            startMove(this, 'borderWidth', 20);
        }

        oDivArray[3].onclick = function () {
            startMove(this, 'opacity', 50);
        }
       
    
    function getStyle (dom, attr) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(dom, null)[attr];
            }else {
                return dom.currentStyle[attr];
            }
        }
   
        function startMove (dom, attr, target) {
            clearInterval(dom.timer);
            var iSpeed = null, iCur = null;
            dom.timer = setInterval(function () {
                if (attr == 'opacity') {
                    iCur = parseFloat( getStyle(dom, attr) ) * 100;
                }else {
                    iCur = parseInt( getStyle(dom, attr) );
                }
                iSpeed = (target - iCur) / 7;
                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                if (iCur == target) {
                    clearInterval(dom.timer);
                }
                if (attr == 'opacity') {
                    dom.style.opacity = ( iCur + iSpeed ) / 100;
                }else {
                    dom.style[attr] = iCur + iSpeed + 'px';
                }   
            }, 30)
        }
     </script>

多物体不同值运动

   <style type="text/css">
    div {
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background: red;
            opacity: 1;
        }
        #topDiv {
            top: 200px;
        }
        #bottomDiv {
            top: 400px;
        }
       
    </style>
</head>
<body>
  <div id="topDiv"></div>
  <div id="bottomDiv"></div> 

   
    <script> 
   
    var timer = null;
       // width -> 100 400   height 100 400   left 0 200  top 200 300 opacity 1 0.5
        // {width: 400, height: 400, left: 200, top: 300, opacity: 50}

        var oTopDiv = document.getElementById('topDiv');
        var oBottomDiv = document.getElementById('bottomDiv');
        oTopDiv.onclick = function () {
        //    当一次性传多值时,且不知道传几个,用对象
            startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
            })
        }
      
    
    function getStyle (dom, attr) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(dom, null)[attr];
            }else {
                return dom.currentStyle[attr];
            }
        }
        function startMove (dom, attrObj) {
            clearInterval(dom.timer);
            var iSpeed = null, iCur = null;
            dom.timer = setInterval(function () {
                var bStop = true;
                //通过循环来改变是属性
                for (var attr in attrObj) {
                    // 'width' 'height' 
                    if (attr == 'opacity') {
                        iCur = parseFloat( getStyle(dom, attr) ) * 100;
                    }else {
                        iCur = parseInt( getStyle(dom, attr) );
                    }
                    iSpeed = (attrObj[attr] - iCur) / 7;
                    iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                    if (attr == 'opacity') {
                       dom.style.opacity = (iCur + iSpeed) / 100; 
                    }else {
                       dom.style[attr] = iCur + iSpeed + 'px';
                    }
                    if (iCur != attrObj[attr]) {
                        bStop = false;
                    }
                }
                if (bStop) {
                    clearInterval(dom.timer);
                    alert("over");
                }
            }, 30);
        }
     </script>

多物体多值运动+回调机制
 <style type="text/css">
    div {
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background: red;
            opacity: 1;
        }
        #topDiv {
            top: 200px;
        }
        #bottomDiv {
            top: 400px;
        }
       
    </style>
</head>
<body>
  <div id="topDiv"></div>
  <div id="bottomDiv"></div> 

   
    <script> 
   
    var timer = null;
       // width -> 100 400   height 100 400   left 0 200  top 200 300 opacity 1 0.5
        // {width: 400, height: 400, left: 200, top: 300, opacity: 50}

        var oTopDiv = document.getElementById('topDiv');
        var oBottomDiv = document.getElementById('bottomDiv');
        oTopDiv.onclick = function () {
        //    当一次性传多值时,且不知道传几个,用对象
            startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
                startMove(oBottomDiv, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
                    alert('over');
                })
            })
        }
      
    
    function getStyle (dom, attr) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(dom, null)[attr];
            }else {
                return dom.currentStyle[attr];
            }
        }
        function startMove (dom, attrObj, callback) {
            clearInterval(dom.timer);
            var iSpeed = null, iCur = null;
            dom.timer = setInterval(function () {
                var bStop = true;
                //通过循环来改变是属性
                for (var attr in attrObj) {
                    // 'width' 'height' 
                    if (attr == 'opacity') {
                        iCur = parseFloat( getStyle(dom, attr) ) * 100;
                    }else {
                        iCur = parseInt( getStyle(dom, attr) );
                    }
                    iSpeed = (attrObj[attr] - iCur) / 7;
                    iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                    if (attr == 'opacity') {
                       dom.style.opacity = (iCur + iSpeed) / 100; 
                    }else {
                       dom.style[attr] = iCur + iSpeed + 'px';
                    }
                    if (iCur != attrObj[attr]) {
                        bStop = false;
                    }
                }
                if (bStop) {
                    clearInterval(dom.timer);
                    typeof callback == 'function' && callback();
                }
            }, 30);
        }
     </script>

加速度运动

   <style type="text/css">
   div {
            position: absolute;
            left: 0px;
            top: 0px;
            width: 100px;
            height: 100px;
            background: orange;
        }
       
    </style>
</head>
<body>
  <div ></div>


   
    <script> 
   
    var timer = null;
            // v = v + at;
        var oDiv = document.getElementsByTagName('div')[0];
        var timer = null;
        oDiv.onclick = function () {
            startMove(this);
        }
        // 加速度不变的加速运动 运动方向是向右
        // 加速度不变的减速运动   加速不变的加速运动 向左
        function startMove (dom) {
            clearInterval(timer);
            var a = 2;
            var iSpeed = 20;
            timer = setInterval(function () {
                iSpeed = iSpeed + a;
                oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
            }, 30);
        };

     </script>

弹性运动

  <style type="text/css">
      div {
            position: absolute;
            left: 0px;
            top: 0px;
            width: 100px;
            height: 100px;
            background: orange;
        }
    
     span {
            position: absolute;
            left: 300px;
            top: 0px;
            background: black;
            width: 2px;
            height: 100px;
        }
       
    </style>
</head>
<body>
<div></div>
<span></span>
   
    <script> 
   var oDiv = document.getElementsByTagName('div')[0];
   var timer  = null;
   oDiv.onclick = function (){
    startMove(this , 300);
   }
   function startMove ( dom , target){
        clearInterval(timer);
        var a =3;
        var ispeed = 0 ;
        //实际损耗  mv
        var u = 0.5 ;
        timer  = setInterval(function(){
           a = (target - dom.offsetLeft) /  10 ;
           ispeed += a;
           //默认摩擦力 
           ispeed *=0.8;
           //在浏览器中运动的物体没有真正的停止,所以近似把绝对值为小于1 看成速度为0
           if ( Math.abs(ispeed) < 1 && Math.abs(target -dom.offsetLeft) <1){
                clearInterval(timer);
                dom.style.left = target + 'px';

           }else{
               dom.style.left = dom.offsetLeft + ispeed +'px';

           }
            dom.style.left = dom.offsetLeft + ispeed + 'px' ;
        },30)
   } 

    
     </script>

弹性运动案例

  <style>
        * {
            padding: 0px;
            margin: 0px;
            list-style: none;
        }

        ul {
            position: relative;
            margin: 100px auto;
            width: 800px;
            height: 100px;
        }

        .ele {
            float: left;
            width: 198px;
            border: 1px solid black;
            height: 98px;
            line-height: 98px;
            text-align: center;
            background: aqua;
        }


        .bg {
            position: absolute;
            left: 0px;
            top: 0px;
            width: 200px;
            height: 100px;
            opacity: 0.5;
            background: deeppink;
        }
    </style>
</head>
<body>

    <ul>
        <li class="ele">CS</li>
        <li class="ele">CG</li>
        <li class="ele">LD</li>
        <li class="ele">DCG</li>
        <li class="bg"></li>
    </ul>
    <script>


    var oLiArray = document.getElementsByTagName('li');
    var oBg = oLiArray[oLiArray.length - 1];
    var timer = null;

    for (var i =0; i < oLiArray.length - 1; i++) {
        oLiArray[i].onmouseenter = function () {
            console.log(this.offsetLeft);
            startMove(oBg, this.offsetLeft);
        }
    }


    function startMove (dom, target) {
        clearInterval(timer);
        var iSpeed = 0;
        var a = 1;
        var u = 0.8;
        timer = setInterval(function () {
            a = (target - dom.offsetLeft) / 5;
            iSpeed += a;
            iSpeed *= u;
            console.log(iSpeed, target - dom.offsetLeft);
            if ( Math.abs(iSpeed)  < 1 && Math.abs(target - dom.offsetLeft) < 1) {
                clearInterval(timer);
                dom.style.left = target + 'px';
            }else {
                dom.style.left = dom.offsetLeft + iSpeed + 'px';
            }
        }, 30);
        }
</script>

模拟重力场
多方向运动+碰撞检测+重力加速度+能量损失
问题1:碰撞边界后反弹的处理

解决:首先要判定边界,在小球向下运动的反弹条件是小球的下边线碰到窗口的下边线,由于存在小球的下边线没有刚好处在窗口下边线的情况,则反弹的判定条件是,让小球的offsetTop(小球上边线与窗口的上边线的距离)大于等于窗口可视区的高度减去小球的直径(高度),此时为了防止反弹点不在窗口底边线,则设置小球的offsetTop等于窗口可视区的高度减去小球的直径。反弹后垂直方向上的速度方向改变,可设置speed = -speed;小球在向上运动时反弹的点在上边线上,此时的处理与下边线类似;左右碰撞原理与上下碰撞原理类似,不做赘述。

问题2:碰撞后的动能损耗

解决:动能损耗直观上来讲,就是速度降低,这里拟损耗后的速度为损耗前的0.8倍

问题3:清理定时器的条件

解决:现实中小球停止时,水平和垂直方向的速度均为零,且落在地面上。而模拟的过程发现小球的速度不能为零,但是数值太小不足以引起位置变化,故当水平和垂直方向上的速度均小于1,且小球下边线在窗口下边线(小球的offsetTop等于窗口可视区的高度减去小球的直径)时,设置速度为零并清理定时器。

    <style>
        div {
            width: 100px;
            height: 100px;
            background: orange;
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div id="demo"></div>
    <script>
        var oDiv = document.getElementById('demo');

        oDiv.onclick = function () {
            startMove(this);
        }

        function startMove (dom) {
            clearInterval(dom.timer);
            var iSpeedX = 6;
            var iSpeedY = 8;
            var g = 3;//重力加速度
            dom.timer = setInterval(function () {
                iSpeedY += g;
                var newTop = dom.offsetTop + iSpeedY;
                var newLeft = dom.offsetLeft + iSpeedX;
               
                if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {
                    iSpeedY *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;
              
                    newTop = document.documentElement.clientHeight - dom.clientHeight;
                }

                if (newTop <= 0) {
                    iSpeedY *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;                    
                    newTop = 0;
                }

                if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {
                    iSpeedX *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;                    
                    newLeft = document.documentElement.clientWidth - dom.clientWidth;
                }

                if (newLeft <= 0) {
                    iSpeedX *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;                    
                    newLeft = 0;
                }
                
                //做停止的判断
                if (Math.abs(iSpeedX) < 1) {
                    iSpeedX = 0;
                }

                if (Math.abs(iSpeedY) < 1) {
                    iSpeedY = 0;
                }


                if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom.clientHeight) {
                    clearInterval(dom.timer);
                    console.log('over')
                }else {
                    dom.style.top = newTop + 'px';
                    dom.style.left = newLeft + 'px';
                }
            }, 30);
       }
    </script>

拖拽实例

 <style>
        div {
            width: 100px;
            height: 100px;
            background: orange;
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div id="demo"></div>
    <script>
        var oDiv = document.getElementById('demo');
        var lastX = 0;
        var lastY = 0;
        var iSpeedX = 0;
        var iSpeedY = 0;
        oDiv.onmousedown = function (e) {
            clearInterval(this.timer);
            var event = event || e;
            //鼠标距离左侧的位置        鼠标指针相对于浏览器页面(或客户区)的水平坐标。     距离边界的位置
            var disX = event.clientX - this.offsetLeft;
            var disY = event.clientY - this.offsetTop;
            var self = this;
            document.onmousemove = function (e) {
                var event = event || e;
                var newLeft = event.clientX - disX;
                var newTop = event.clientY - disY;

                //计算松手时的速度
                iSpeedX = newLeft - lastX;
                iSpeedY = newTop - lastY;

                //更新最后松手前的位置
                lastX = newLeft;
                lastY = newTop;

                // //拖拽时留下的痕迹
                // var oSpan = document.createElement('span');
                // oSpan.style.position = 'absolute';
                // oSpan.style.left = newLeft + 'px';
                // oSpan.style.top = newTop + 'px';
                // oSpan.style.width = '5px';
                // oSpan.style.height = '5px';
                // oSpan.style.backgroundColor = 'black';
                // document.body.appendChild(oSpan);


                self.style.left = newLeft + 'px';
                self.style.top = newTop + 'px';
            }
            document.onmouseup = function () {
                document.onmouseup = null;
                document.onmousemove = null;
                startMove(self, iSpeedX, iSpeedY);
            }
        }

        function startMove(dom, iSpeedX, iSpeedY) {
            clearInterval(dom.timer);

            var g = 3; //重力加速度
            dom.timer = setInterval(function () {
                iSpeedY += g;
                var newTop = dom.offsetTop + iSpeedY;
                var newLeft = dom.offsetLeft + iSpeedX;

                if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {
                    iSpeedY *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;

                    newTop = document.documentElement.clientHeight - dom.clientHeight;
                }

                if (newTop <= 0) {
                    iSpeedY *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;
                    newTop = 0;
                }

                if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {
                    iSpeedX *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;
                    newLeft = document.documentElement.clientWidth - dom.clientWidth;
                }

                if (newLeft <= 0) {
                    iSpeedX *= -1;
                    //能量损失
                    iSpeedY *= 0.8;
                    iSpeedX *= 0.8;
                    newLeft = 0;
                }

                //做停止的判断
                if (Math.abs(iSpeedX) < 1) {
                    iSpeedX = 0;
                }

                if (Math.abs(iSpeedY) < 1) {
                    iSpeedY = 0;
                }


                if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom
                    .clientHeight) {
                    clearInterval(dom.timer);
                    console.log('over')
                } else {
                    dom.style.top = newTop + 'px';
                    dom.style.left = newLeft + 'px';
                }
            }, 30);
        }
    </script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值