zoukankan      html  css  js  c++  java
  • javascript运动详解

    javascript运动详解

    本文给大家详细介绍下如何使用javascript来实现运动效果,总结的十分全面,附上各种效果的详细示例和演示图,有需要的小伙伴可以参考下。
     

    物体运动原理:通过改变物体的位置,而发生移动变化。

    方法:

    1.运动的物体使用绝对定位 
    2.通过改变定位物体的属性(left、right、top、bottom)值来使物体移动。例如向右或左移动可以使用offsetLeft(offsetRight)来控制左右移动。

    步骤:

    1、开始运动前,先清除已有定时器 (因为:是连续点击按钮,物体会运动越来越快,造成运动混乱)
    2、开启定时器,计算速度
    3、把运动和停止隔开(if/else),判断停止条件,执行运动

    一.定时器

    在javascritp中,有两个关于定时器的专用函数,它们是: 

    1.倒计定时器:timename=setTimeout("function();",delaytime);
    2.循环定时器:timename=setInterval("function();",delaytime); 

      function()是定时器触发时要执行的是事件的函数,可以是一个函数,也可以是几个函数,或者javascript的语句也可以,单要用;隔开;delaytime则是间隔的时间,以毫秒为单位。 

      倒计时定时器就是在指定时间后触发事件,而循环定时器就是在间隔时间到来时反复触发事件,其区别在于:前者只是作用一次,而后者则不停地作用。 

      倒计时定时器一般用于页面上只需要触发一次的的情况,比如点击某按钮后页面在一定时间后跳转到相应的站点,也可以用于判断一个浏览者是不是你的站点上的“老客”,如果不是,你就可以在5秒或者10秒后跳转到相应的站点,然后告诉他以后再来可以在某个地方按某一个按钮就可以快速进入。 

      循环定时器一般用于站点上需要从复执行的效果,比如一个javascript的滚动条或者状态栏,也可以用于将页面的背景用飞雪的图片来表示。这些事件需要隔一段时间运行一次。 

      有时候我们也想去掉一些加上的定时器,此时可以用clearTimeout(timename) 来关闭倒计时定时器,而用clearInterval(timename)来关闭循环定时器。

    二.运动研究

    1.运动:匀速运动(让物体动起来)

    对定时器的使用
    给DIV加绝对定位
    offsetLeft

    问题:到达某个特定位罝停符
    解决:做判断,符合条件时关掉定时器(存定时器timer)
    速度变慢(一般不动时间,而是改数字-速度)
    用变量存速度

    问题:取7时,offsetLeft没有等于300的时候,div停不下来 
    解决:>=300 //停在 301

    问题:到300后点击按钮还继续走
    原因:点击按钮,执行函数,开定时器(执行当前函数一至少执行一次) 
    解决:加else (没有到达目标之前才执行)

    问题:连续点击,速度变快
    原因:每点击一次就开一个定时器,点击几次就有几个定时器同时工作 
    解决:保证每次只有一个定时器工作,先cearlnterval ()

    示例1,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>分享到</title>
    <style>
    #div1 {150px; height:200px; background:green; position:absolute; left:-150px;}
    #div1 span {position:absolute; 20px; height:60px; line-height:20px; background:blue; right:-20px; top:70px;}
    </style>
    <script>
    window.onload=function ()
    {
      var oDiv=document.getElementById('div1');
       
      oDiv.onmouseover=function ()
      {
        startMove(0);
      };
      oDiv.onmouseout=function ()
      {
        startMove(-150);
      };
    };
     
    var timer=null;
     
    function startMove(iTarget)
    {
      var oDiv=document.getElementById('div1');
       
      clearInterval(timer);
      timer=setInterval(function (){
        var speed=0;
         
        if(oDiv.offsetLeft>iTarget)
        {
          speed=-10;
        }
        else
        {
          speed=10;
        }
         
        if(oDiv.offsetLeft==iTarget)
        {
          clearInterval(timer);
        }
        else
        {
          oDiv.style.left=oDiv.offsetLeft+speed+'px';
        }
      }, 30);
    }
    </script>
    </head>
     
    <body>
    <div id="div1">
      <span>分享到</span>
    </div>
    </body>
    </html>

    效果如下:

    示例2,淡入淡出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>淡入淡出</title>
    <style>
    #div1 {200px; height:200px; background:red; filter:alpha(opacity:30); opacity:0.3;}
    </style>
    <script>
    window.onload=function ()
    {
      var oDiv=document.getElementById('div1');
       
      oDiv.onmouseover=function ()
      {
        startMove(100);
      };
      oDiv.onmouseout=function ()
      {
        startMove(30);
      };
    };
     
    var alpha=30;
    var timer=null;
     
    function startMove(iTarget)
    {
      var oDiv=document.getElementById('div1');
       
      clearInterval(timer);
      timer=setInterval(function (){
        var speed=0;
         
        if(alpha<iTarget)
        {
          speed=10;
        }
        else
        {
          speed=-10;
        }
         
        if(alpha==iTarget)
        {
          clearInterval(timer);
        }
        else
        {
          alpha+=speed;
           
          oDiv.style.filter='alpha(opacity:'+alpha+')';
          oDiv.style.opacity=alpha/100;
        }
      }, 30);
    }
    </script>
    </head>
     
    <body>
    <div id="div1"></div>
    </body>
    </html>

    效果如下:

    匀速运动的停止条件

    距离足够近

    示例3,匀速运动的停止条件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>匀速运动的停止条件</title>
    <style>
    #div1 {100px; height:100px; background:red; position:absolute; left:600px; top:50px;}
    #div2 {1px; height:300px; position:absolute; left:300px; top:0; background:black;}
    #div3 {1px; height:300px; position:absolute; left:100px; top:0; background:black;}
    </style>
    <script>
    var timer=null;
     
    function startMove(iTarget)
    {
      var oDiv=document.getElementById('div1');
       
      clearInterval(timer);
      timer=setInterval(function (){
        var speed=0;
         
        if(oDiv.offsetLeft<iTarget)
        {
          speed=7;
        }
        else
        {
          speed=-7;
        }
         
        if(Math.abs(iTarget-oDiv.offsetLeft)<=7)
        {
          clearInterval(timer);
           
          oDiv.style.left=iTarget+'px';
        }
        else
        {
          oDiv.style.left=oDiv.offsetLeft+speed+'px';
        }
      }, 30);
    }
    </script>
    </head>
     
    <body>
    <input type="button" value="到100" onclick="startMove(100)" />
    <input type="button" value="到300" onclick="startMove(300)" />
    <div id="div1"></div>
    <div id="div2"></div>
    <div id="div3"></div>
    </body>
    </html>

    2.变速运动(缓冲运动)

    逐渐变慢,最后停止 
    距离越远速度越大 
    速度有距离决定
    速度=(目标值-当前值)/缩放系数 
    如果没有缩放系数t速度太大,瞬间到达终点.没有过程

    问题:并没有真正到达300
    原因:速度只剩0.9 //像素是屏幕能够显示的最/J库位,并不会四舍五入掉
    Math.ceil ()向上取整
    Math.floor ()向下取整

    问题:向左走,又差一块--Math.floor ()
    判断:三目 speed=speed>0 ? Math.ceil ( speed ): Math.floor ( speed )

    示例,缓冲运动:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>缓冲运动</title>
    <style>
    #div1 {100px; height:100px; background:red; position:absolute; left:600px; top:50px;}
    #div2 {1px; height:300px; position:absolute; left:300px; top:0; background:black;}
    </style>
    <script>
    function startMove()
    {
      var oDiv=document.getElementById('div1');
      setInterval(function (){
        var speed=(300-oDiv.offsetLeft)/10;
        speed=speed>0?Math.ceil(speed):Math.floor(speed);
         
        oDiv.style.left=oDiv.offsetLeft+speed+'px';
         
        document.title=oDiv.offsetLeft+','+speed;
      }, 30);
    }
    </script>
    </head>
     
    <body>
    <input type="button" value="开始运动" onclick="startMove()" />
    <div id="div1"></div>
    <div id="div2"></div>
    </body>
    </html>

    效果如下:

    3.多物体运动

    多个div ,鼠标移入变宽
    运动框架传参obj,知道让哪个物体动起来
    用到缓冲一定要取整

    问题:div没运动回去 //清除前一个定时器
    原因:只有一个定时器
    解决:加物体上的定时器,使每个物体都有一个定时器。定时器作为物体属性

    多个div淡入淡出
    首先关闭物体上的定时器
    经验:多物体运动框架所有东西都不能共用

    问题:不是因为定时器,而是因为alpha
    解决:作为属性附加到物体上 /不以变量形式存在

    offset 的 bug

    加border变宽

    offsetWith并不是真正的width ,它获取的是盒模型尺寸 
    解决:躲着 宽度扔到行间,parselnt ( oDiv.style.width )

    进一步解决: getStyle ( obj, name ) currentStyle , getComputedStyle 
    加border ,只要offset就有问题 去掉offset

    示例,多物体运动:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>无标题文档</title>
    <style>
    div {100px; height:50px; background:red; margin:10px; border:10px solid black;}
    </style>
    <script>
    window.onload=function ()
    {
      var aDiv=document.getElementsByTagName('div');
       
      for(var i=0;i<aDiv.length;i++)
      {
        aDiv[i].timer=null;
         
        aDiv[i].onmouseover=function ()
        {
          startMove(this, 400);
        };
         
        aDiv[i].onmouseout=function ()
        {
          startMove(this, 100);
        };
      }
    };
     
    function startMove(obj, iTarget)
    {
      clearInterval(obj.timer);
      obj.timer=setInterval(function (){
        var speed=(iTarget-obj.offsetWidth)/6;
        speed=speed>0?Math.ceil(speed):Math.floor(speed);
         
        if(obj.offsetWidth==iTarget)
        {
          clearInterval(obj.timer);
        }
        else
        {
          obj.style.width=obj.offsetWidth+speed+'px';
        }
      }, 30);
    }
    </script>
    </head>
     
    <body>
    <div></div>
    <div></div>
    <div></div>
    </body>
    </html>

    效果如下:

    4.任意值运动

    任意值运动的单位分为透明度和px。

    px单位的任意值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="utf-8">
    <title>无标题文档</title>
    <style>
    div {200px; height:200px; margin:20px; float:left; background:yellow; border:10px solid black; font-size:14px;}
    </style>
    <script>
    window.onload=function ()
    {
      var oDiv1=document.getElementById('div1');
      oDiv1.onmouseover=function (){startMove(this, 'height', 400);};
      oDiv1.onmouseout=function (){startMove(this, 'height', 200);};
       
      var oDiv2=document.getElementById('div2');
       
      oDiv2.onmouseover=function (){startMove(this, 'width', 400);};
      oDiv2.onmouseout=function (){startMove(this, 'width', 200);};
       
      var oDiv3=document.getElementById('div3');
      oDiv3.onmouseover=function (){startMove(this, 'fontSize', 50);};
      oDiv3.onmouseout=function (){startMove(this, 'fontSize', 14);};
       
      var oDiv4=document.getElementById('div4');
      oDiv4.onmouseover=function (){startMove(this, 'borderWidth', 100);};
      oDiv4.onmouseout=function (){startMove(this, 'borderWidth', 10);};
    };
     
    function getStyle(obj, name)
    {
      if(obj.currentStyle){return obj.currentStyle[name];}
      else{return getComputedStyle(obj, false)[name];}
    }
     
    function startMove(obj, attr, iTarget)
    {
      clearInterval(obj.timer);
      obj.timer=setInterval(function (){
        var cur=parseInt(getStyle(obj, attr));
         
        var speed=(iTarget-cur)/6;
        speed=speed>0?Math.ceil(speed):Math.floor(speed);
         
        if(cur==iTarget)
        {
          clearInterval(obj.timer);
        }
        else
        {
          obj.style[attr]=cur+speed+'px';
        }
      }, 30);
    }
    </script>
    </head>
     
    <body>
    <div id="div1">变高</div>
    <div id="div2">变宽</div>
    <div id="div3">safasfasd</div>
    <div id="div4"></div>
    </body>
    </html>

    效果如下:

    透明度的任意值,需要做判断:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    判断
    var cur=0
    if ( attr== 'opacity '){
    cur=parseFloat ( getStyle ( obj, attr)) *100
    }else{
     
    }
    设置样式判断
    if ( attr== 'opacity '){
    obj.style.fiIter = 'alpha ( opacity: '( cur+speed ) + ')'
    obj.style.opacity= ( cur+speed ) /100
    }else{
     
    }

    5.链式运动

    多出来的一个参数,只有传进去的时候才调用
    鼠标移入变宽,结束之后弹出abc
    先横向展开.再以向展开
    鼠标移出,先变回不透明,变矮,变窄

    三.封装运动框架(源码下载:https://github.com/jingwhale/jsmove/blob/master/move.js)

    基于以上的分析与总结,封装运动框架move.js如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    function getStyle(obj, name)
    {
      if(obj.currentStyle)
      {
        return obj.currentStyle[name];
      }
      else
      {
        return getComputedStyle(obj, false)[name];
      }
    }
     
    function startMove(obj, json, fnEnd)
    {
      clearInterval(obj.timer);
      obj.timer=setInterval(function (){
        var bStop=true;    //假设:所有值都已经到了
         
        for(var attr in json)
        {
          var cur=0;
           
          if(attr=='opacity')
          {
            cur=Math.round(parseFloat(getStyle(obj, attr))*100);
          }
          else
          {
            cur=parseInt(getStyle(obj, attr));
          }
           
          var speed=(json[attr]-cur)/6;
          speed=speed>0?Math.ceil(speed):Math.floor(speed);
           
          if(cur!=json[attr])
            bStop=false;
           
          if(attr=='opacity')
          {
            obj.style.filter='alpha(opacity:'+(cur+speed)+')';
            obj.style.opacity=(cur+speed)/100;
          }
          else
          {
            obj.style[attr]=cur+speed+'px';
          }
        }
         
        if(bStop)
        {
          clearInterval(obj.timer);
                 
          if(fnEnd)fnEnd();
        }
      }, 30);
    }

    move.js运动框架基本满足现在网页上所有动画的需求(不包括css3)。

    四.应用应用

    1,完成如下效果:

    js代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <script src="move.js"></script>
    <script>
    window.onload=function ()
    {
      var oDiv=document.getElementById('play');
      var aBtn=oDiv.getElementsByTagName('ol')[0].getElementsByTagName('li');
      var oUl=oDiv.getElementsByTagName('ul')[0];
       
      var now=0;
      for(var i=0;i<aBtn.length;i++)
      {
        aBtn[i].index=i;
        aBtn[i].onclick=function ()
        {
          now=this.index;
          tab();
        };
      }
       
      function tab()
      {
        for(var i=0;i<aBtn.length;i++)
        {
          aBtn[i].className='';
        }
        aBtn[now].className='active';
        startMove(oUl, {top: -150*now});
      }
       
      function next()
      {
        now++;
        if(now==aBtn.length){now=0;}
        tab();
      }
       
      var timer=setInterval(next, 2000);
       
      oDiv.onmouseover=function (){clearInterval(timer);};
       
      oDiv.onmouseout=function (){timer=setInterval(next, 2000);};
    };
    </script>

    应用2,完成如下效果:

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>无标题文档</title>
    <style type="text/css">
    .....
    </style>
    <script type="text/javascript" src="move.js"></script>
    <script type="text/javascript">
    window.onload=function ()
    {
      var oBtn=document.getElementById('but');
      var oBottom=document.getElementById('zns_bottom');
      var oBox=document.getElementById('zns_box');
      var oBtnClose=document.getElementById('btn_close');
       
      oBox.style.display='block';
      var initBottomRight=parseInt(getStyle(oBottom, 'right'));
      var initBoxBottom=parseInt(getStyle(oBox, 'bottom'));
      oBox.style.display='none';
       
      oBtn.onclick=openHandler;
      oBtnClose.onclick=closeHandler;
       
      function openHandler()
      {
        startMove(oBottom, {right: 0}, function (){
          oBox.style.display='block';
          startMove(oBox, {bottom: 0});
        });
        oBtn.className='but_hide';
        oBtn.onclick=closeHandler;
      }
       
      function closeHandler()
      {
        startMove(oBox, {bottom: initBoxBottom}, function (){
          oBox.style.display='none';
          startMove(oBottom, {right: initBottomRight}, function (){
            oBtn.className='but_show';
          });
        });
        oBtn.onclick=openHandler;
      }
    };
    </script>
    </head>
    <body>
      ......
    </body>
    </html>

    源码下载:https://github.com/jingwhale/jsmove

  • 相关阅读:
    mysql随手记
    Exception 和 RuntimeException区别
    数据结构与算法
    Idea快捷键
    eclipse快捷键
    了解Lua语言中的_index,newindex,rawget和rawset
    Cocos2d-x CCNotificationCenter 通知中心
    LUA-赋值语句
    CCOrbitCamera:create
    类型和值
  • 原文地址:https://www.cnblogs.com/xiaoshujiang/p/5538734.html
Copyright © 2011-2022 走看看