浅析JS运动


Posted in Javascript onDecember 28, 2015

物体运动原理:通过改变物体的位置,而发生移动变化。 任何运动都是相对的,就像物理中的运动公式:s(要达到的)=s0(当前的样式值)+vt。

方法:
      1.运动的物体使用绝对定位
      2.通过改变定位物体的属性(left、right、top、bottom)值来使物体移动。例如向右或左移动可以使用offsetLeft(offsetRight)来控制左右移动。
步骤:
    1、开始运动前,先清除已有定时器 (因为:是连续点击按钮,物体会运动越来越快,造成运动混乱)
    2、开启定时器,计算速度
    3、把运动和停止隔开(if/else),判断停止条件,执行运动

关键点:

1、多物体

将定时器附在对象上
2、链式运动

循环调用定时器:fnEnd函数里开启另外的定时器
3、多值运动

循环属性值数组:一个定时器时间,执行多个属性值得改变
判断运动结束,所有属性都到预定的值:增加一个布尔值标志,开始时,var bStop=true;     //假设:所有值都已经到了;在循环的时候判断,如果if(cur!=json[attr])   bStop=false;

一.定时器
在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,分享到:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>分享到</title>
<style>
#div1 {width:150px; height:200px; background:green; position:absolute; left:-150px;}
#div1 span {position:absolute; width: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>

效果如下:

浅析JS运动

示例2,淡入淡出:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>淡入淡出</title>
<style>
#div1 {width: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>

效果如下:

浅析JS运动

匀速运动的停止条件
距离足够近

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

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>匀速运动的停止条件</title>
<style>
#div1 {width:100px; height:100px; background:red; position:absolute; left:600px; top:50px;}
#div2 {width:1px; height:300px; position:absolute; left:300px; top:0; background:black;}
#div3 {width: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 )

示例,缓冲运动:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>缓冲运动</title>
<style>
#div1 {width:100px; height:100px; background:red; position:absolute; left:600px; top:50px;}
#div2 {width: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>

效果如下:

浅析JS运动

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

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

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

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

offset 的 bug

加border变宽

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

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

示例,多物体运动:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style>
div {width: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>

效果如下:

浅析JS运动

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

px单位的任意值

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style>
div {width: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>

效果如下:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style>
div {width: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>

效果如下:

浅析JS运动

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

判断
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
先横向展开.再以向展开
鼠标移出,先变回不透明,变矮,变窄

三.封装运动框架

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

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)。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
js变量作用域及可访问性的探讨
Nov 23 Javascript
用Javascript数组处理多个字符串的连接问题
Aug 20 Javascript
javascript测试题练习代码
Oct 10 Javascript
JavaScript实现找质数代码分享
Mar 24 Javascript
详解JavaScript的策略模式编程
Jun 24 Javascript
JS遍历JSON数组及获取JSON数组长度操作示例【测试可用】
Dec 12 Javascript
详解一个基于套接字实现长连接的express
Mar 28 Javascript
Layui之table中的radio在切换分页时无法记住选中状态的解决方法
Sep 02 Javascript
vue.js实现只能输入数字的输入框
Oct 19 Javascript
VueQuillEditor富文本上传图片(非base64)
Jun 03 Javascript
React实现todolist功能
Dec 28 Javascript
详解uniapp的全局变量实现方式
Jan 11 Javascript
基于JavaScript实现网页倒计时自动跳转代码
Dec 28 #Javascript
js时间戳转为日期格式的方法
Dec 28 #Javascript
jquery实现全屏滚动
Dec 28 #Javascript
AngularJS使用angular-formly进行表单验证
Dec 27 #Javascript
延时加载JavaScript代码提高速度
Dec 27 #Javascript
AngularJS使用ngMessages进行表单验证
Dec 27 #Javascript
详解maxlength属性在textarea里奇怪的表现
Dec 27 #Javascript
You might like
PHP 身份验证方面的函数
2009/10/11 PHP
PHP最常用的ini函数分析 针对PHP.ini配置文件
2010/04/22 PHP
用php解析html的实现代码
2011/08/08 PHP
浅析PHP页面局部刷新功能的实现小结
2013/06/21 PHP
thinkPHP导出csv文件及用表格输出excel的方法
2015/12/30 PHP
php传值方式和ajax的验证功能
2017/03/27 PHP
Laravel实现批量更新多条数据
2020/04/06 PHP
JAVASCRIPT 对象的创建与使用
2021/03/09 Javascript
JavaScript 获取当前时间戳的代码
2010/08/05 Javascript
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
JS模拟面向对象全解(二、类型与赋值)
2011/07/13 Javascript
sencha touch 模仿tabpanel导航栏TabBar的实例代码
2013/10/24 Javascript
jQuery获取多种input值的简单实现方法
2016/06/20 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
Bootstrap基本插件学习笔记之轮播幻灯片(23)
2016/12/08 Javascript
详解Nodejs之npm&amp;package.json
2017/06/15 NodeJs
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
JS实现头条新闻的经典轮播图效果示例
2019/01/30 Javascript
layui--js控制switch的切换方法
2019/09/03 Javascript
jQuery实现每日秒杀商品倒计时功能
2019/09/06 jQuery
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
2020/02/12 Javascript
JS操作Fckeditor的一些常用方法(获取、插入等)
2020/02/19 Javascript
Javascript实现打鼓效果
2021/01/29 Javascript
[05:08]第一届“网鱼杯”DOTA2比赛精彩集锦
2014/09/05 DOTA
Windows上配置Emacs来开发Python及用Python扩展Emacs
2015/11/20 Python
举例讲解Python中的Null模式与桥接模式编程
2016/02/02 Python
python 地图经纬度转换、纠偏的实例代码
2018/08/06 Python
Python利用heapq实现一个优先级队列的方法
2019/02/03 Python
阿迪达斯越南官网:adidas越南
2020/07/19 全球购物
AJAX的优缺点都有什么
2015/08/18 面试题
90后毕业生的求职信范文
2013/09/21 职场文书
售后服务经理岗位职责
2014/02/25 职场文书
打架赔偿协议书范本
2014/10/26 职场文书
同事打架检讨书
2015/05/06 职场文书
2016年庆祝六一儿童节活动总结
2016/04/06 职场文书
详解Python自动化之文件自动化处理
2021/06/21 Python