JS操控CSS样式完成小球自由落体运动,和大家分享一下制作心得。

原创
2013/07/17 12:51
阅读数 3.8K

    这篇心得本应该在一个月之前和大家一起分享的,由于本人比较懒,也几乎没有写博客的习惯,所以迟了一些。有一些内容只是一些个人的废话,可看可不看,毕竟在国内的应试教育下,大家基础物理知识都是很扎实的:

    (废话)(背景:下面讨论的物体运动默认为宏观角度)一般情况下,物体在三维空间所发生的位移都可以解析为若干连续的在二维空间所发生的位移的和,同理,物体在二维空间所发生的位移也可以解析为若干连续的在一维空间所发生位移的和。基于这个思想(本人的个人体会,对错有待验证),往往一个物体复杂的运动,若将其位移解析为不同一维空间所发生位移的总和,则会让我们能更好地去理解和模拟物体的运动规律。 

    (废话) 关于自由落体,若在外部环境稳定的情况下,我们可以视其为一个有规律的运动(所谓有规律的运动,运动的方式或过程具有周期性,可重复性),这样我们在写代码的时候,只要抓住其第一个周期的运动规律和初始状态,整个运功过程就可以被复制下来。

    (废话) 在中学时期,我们都学过自由落体,老师教我们将它的运动过程解析为水平方向(X轴)和竖直方向(Y轴)的运动轨迹之和,本人能力有限,对物体的运动规律理解不够深刻,所以不能跳出教科书所给定的常规方法,故也采用此法,若不能带给大家更多新的东西,望见谅。

(废话)如何理解位移:简单地说,就是物体在下一时刻所处的位置交上一时刻所处的位置的“差”,为了处理方便,这里的“差”我们理解为两个时刻所处位置的数值上的不同。

(我感觉越说越跑题了,再这样下去就绕不回来了。。下面进入正题,一切理论依据都将参考“大家的物理常识):()

—————————————————————————————————————————————————————

      小球自由落体中,最核心的就是Y轴的运动了,运动过程:

      1、从初始位置下落:初始下落速度为0,我们把空气的阻力与地球引力和为在竖直方向上的一个外力,则小球在竖直方向上只受一个外力作用,从而产生竖直方向的速度和加速度,(因为是模仿,所以这个值我们可以自己设定,但必须有),因为自由落体的速度和加速度与物体的质量无关,所以不考虑质量;

      2、小球落地与地面碰撞: 碰撞的瞬间,小球发生形变,能量损耗,反弹后的初始速度将小于即将落地时的下落速度,由于JS下无法体现“能量”,则将转化为“速度”进行处理,能量损耗则以速度的不同来体现;

      3、小球反弹后上升:上升到最高点,速度为0,准备下落。

  (小球的速度不同体现为力作用在小球上的时间差,这个时间差很重要!)

过程1、2、3则为自由落体的一个周期,直到最终小球能够上升的最高点与地面相等,整个自由落体运动结束。

下面将通过代码加注释的方法让大家更为直观地了解其过程:

<html>
<head>
    <title></title>
    <meta http-equiv="content-type" content="text/html" charset="utf-8"/>
    <style type="text/css">
        *{margin: 0;padding: 0;}
        #ball{
            width: 15px;height:15px;
            border-top-left-radius:8px;
            border-top-right-radius:8px;
            border-bottom-left-radius:8px;
            border-bottom-right-radius:8px;
            background-color:purple;
        }
    </style>
</head>
<body>
 <div id="ball" style="position: absolute;top:0px;left:0px"></div>  <!-- -------创建小球---------->
 <button style="margin-left: 20px" onclick="">start</button>
<script type="text/javascript">
    var dball = document.getElementById("ball");
    var width = screen.availWidth;                  ////获得屏幕可用宽度,考虑碰撞
    var height = screen.availHeight;                ////获得屏幕可用高度,考虑碰撞
    var leftposition =parseInt( dball.style.left);  ////获得小球左侧坐标(理解为小球的横向位置)
    var topposition =parseInt(dball.style.top);       ////获得小球上端坐标(理解为小球的纵向向位置)
    var bool=true;                                  //判断小球是否落到地面碰撞,速度增量得由正变为负了
    var boolx =true;                                 //X方向判断是否撞墙需反弹(反弹就是速度由正变为负)  
    var t00= 0,t01= 0;              //t00为小球下落期间,下落的上一个时刻,t01为下一个时刻
    var t10= 0,t11=0;               //t10为小球上升期间,上升的上一个时刻,t11为下一个时刻
    var step=0.1;                   //step为上一个时刻和下一个时刻的时间差
    var speedy= 0;                  //小球下落阶段的位移增量(可以理解为下落时某一时间的速度值)
    var speedy1=0;                  //小球上升阶段的位移增量(可以理解为上升时某一时间的速度值)
    var speedym=0;                  //用来保存小球与地面碰撞的瞬间时的位移增量(即小球下落时的最大速度)
    var a=1.2;                      //小球反弹后,交反弹前的速度损失比例(可以理解为能量损耗)
/////////////////////////水平方向的X位移,匀速运动,没啥看头//////////////////////////////////
        function xmove(){
          var speedx=2;
          leftposition =parseInt( dball.style.left);
          if(leftposition+15>=width){boolx=true;}
           if(leftposition<0){boolx=false}
          if(boolx){speedx=-2;}else speedx=2;
           dball.style.left =leftposition+speedx+"px";
       }
      var doxmove =setInterval("xmove()",10);   /////线程未设清除,不关闭页面则一直会动下去
/////////////////////////////////////////////竖直方向的Y位移,核心部分//////////////////////////
       function move()
       {
         if(bool){         ////////初始化为true,则下落
         t01=t00+step;                       // 时间段1: 下一时刻相比于上一时刻
         speedy =5*(t01*t01-t00*t00);         //由公式S=1/2gt1²-1/2gt0²转化而来,g设定为10;
         t00=t01;           // 时间段1 的下一时刻 则是 时间段2的上一时刻 (有点绕,可以理解为T0~T1为一个                                    时间段,T2~T3为相邻的下一个时间段,则T1==T2)
             topposition=parseInt(dball.style.top); 
             dball.style.top=topposition+speedy+"px";       /////小球在某一时刻的位置变化
      if(topposition+100>=height){
     speedym=speedy;   //////保存最大位移增量,为下面反弹记录反弹时的初始位移增量(反弹的初始速度)
     t00=0;t01=0; //此时,下落过程结束,必须初始化两个时刻(因为时刻不同,反应出的位移增量(速度)也不同)
      bool=false;        ///// 改变状态,得上升了
                                           }   
         }
        else{
         t11=t10+step;    //上升阶段和下落阶段的本质区别在于:下落阶段的初始速度为 0,上升阶段的初始速度为一个不为0的向上的值,其他的过程和状态都一致
             speedy1 =5*(t11*t11-t10*t10);
             t10=t11;
             topposition=parseInt(dball.style.top);
        dball.style.top=topposition-(speedym/a)+speedy1+"px"; //  (speedym/a)为上升阶段的初始位移增量(速度),a为能耗
             if(speedy1-(speedym/a)>=0){     //  向下的位移增量(速度)和初始位移增量(速度)相等时,小球上升到最大高度,此时位移增量为0,改下落了
                                        t10=0;t11=0;               
                                        bool=true;
                                        a=a+0.05;                 //因为每撞击一次,小球第二次的下落速度会变小,因为速度越小,撞击时能量损耗越大,所以能量损耗比例越高
                                        }                         //这也是模拟客观物体运动所需
         }
       }
         var doymove =setInterval("move()",10);                    //每10毫秒运行一次。没有关闭线程哦,但小球最终会在Y方向停下来,并不需要人为给它停止 。 (小球虽然停了,但线程依然在执行哦)
</script>
</body>
</html>

-------------------------------------------------------------------------------------------------------------------

   上面的代码,所有过程都是模拟物体运动规律,涉及到动量、能量的部分都以位移量的方式进行了转化,如果有哪些地方介绍的不清楚或者有不理解的地方可以给我留言。 

     如果有更好的模拟方法,希望大家能够介绍给我,谢谢!!!!

   代码可以直接复制粘贴运行。。。。。。。。。。。




































展开阅读全文
打赏
0
7 收藏
分享
加载中
更多评论
打赏
0 评论
7 收藏
0
分享
返回顶部
顶部