实例讲解Javascript缓动效果

开发 前端
这个缓动效果还是不错的,虽然有些缺点。希望本文能对大家了解Javascript缓动效果有所帮助。

我们这里将讨论的是Javascript缓动效果的实现,这个看似没有实际作用的功能,其实实现更多花样繁多Javascript缓动效果的基石。

缓动,学名为Tween,缓冲移动的简称。要想页面内容切换起来舒服,就使用淡入淡出特效,要想让页面元素动起来自然,就要使用Javascript缓动效果。这两个混合起来,可以衍生多种特效的。感谢Flash开发人员为我们做了那么多先行研究,我们直接把它们拆出来装在各种菜单与相册中。我们先从最简单的东西做起,加速与减速。

既然是缓动,它就一定涉及以下概念:距离,时间与速度。我们可以想象存在一条直线L,点A与点B就是L的起点与终点,有一个点C在直线L上移动,从点A到点B。所需的时间通常都是未知,但速度我们一定要制定。看下面的图,我们想让绿色的方块在淡紧色的滑动带上移动。滑动带左上角就相当于点A,右上角就相当于B点,方块的左上角就相当于点C,移动距离为两者的宽度之差。由于我们移动的物体是存在宽度,也就是说点C永远不可能与点B重合。但一个准确的目的地(为了方便,我们把它称之为点D)是必须的,我们一定要计算它出来。因为在加速运动中,点C随时可能超过点D,当点超过它时,我们就要终止此移动,并把点C拉回到点D上。

加速

点击可移动绿色方块

为了获取它们在页面上的坐标与尺寸,getCoords()与getStyle()又到出场时间了。对不起,我实在没有意思来炫耀我的函数。更何况getStyle()被砍去了不少东西,威力没有以前那么强大。

01.//辅助函数1
02.var getCoords = function(el){
03.  var box = el.getBoundingClientRect(),
04.  doc = el.ownerDocument,
05.  body = doc.body,
06.  html = doc.documentElement,
07.  clientTop = html.clientTop || body.clientTop || 0,
08.  clientLeft = html.clientLeft || body.clientLeft || 0,
09.  top  = box.top  + (self.pageYOffset || html.scrollTop  ||  body.scrollTop ) - clientTop,
10.  left = box.left + (self.pageXOffset || html.scrollLeft ||  body.scrollLeft) - clientLeft
11.  return { 'top': top, 'left': left };
12.};
13.//辅助函数2
14.var getStyle = function(el, style){
15.  if(!+"\v1"){
16.    style = style.replace(/\-(\w)/g, function(all, letter){
17.      return letter.toUpperCase();
18.    });
19.    var value = el.currentStyle[style];
20.    (value == "auto")&&(value = "0px" );
21.    return value;
22.  }else{
23.    return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
24.  }
25.}

那么我们怎么移动呢?在Javascript只有让它变为绝对定位对象,给它的top与left赋值。它就会立即移动到相应的坐标上。由于Javascript处理位置变化太有效率,根本不可能让你有“移动”的感觉,感觉是直接从点C直接跳到点D。我们必须让物体每移动一点点,就停一下,让眼睛有个残影。根据人眼睛的视觉停留效应,若前一幅画像留在大脑中的印象还没消失,后一幅画像就接踵而至,而且两副画面间的差别很小,就会有“动”的感觉。那么停留多么毫秒最合适呢?我们不但要照顾人的眼睛,还要顾及一下显示器的显示速度与浏览器的渲染速度。根据外国的统计,25毫秒为***数值。其实,这个数值我们应该当作常识来记住。联想一下,日本动画好像有个规定是1秒30张画,中国的,比较垃圾,是1秒24张。用1秒去除以张数,就得到每张停留的时间。日本的那个27.77毫秒已经很接近我们的25毫秒了,因为浏览器的渲染速度明显不如电视机的渲染速度,尤其是IE6这个拉后腿的。要实现加速度,就是让它每次移动快一点点,让上一次移动的距离乘以一个大于1的数便可。

01.//辅助函数3,相当于$(),不用$符号命名是因为博客园在用JQuery,会引起命名冲突
02.//我新一代查代元素的方法,拥有缓存能力
03.var cache = []
04.var _ = function(id){
05.  return cache[id] || (cache[id] = document.getElementById(id));
06.}
07.//主函数:加速移动
08.var accelerate= function(el){
09.  el.style.position = "absolute";
10.  var begin =  getCoords(el).left,
11.  distance = parseFloat(getStyle(_("taxiway"),"width")) - parseFloat(getStyle(el,"width")),
12.  end = begin + distance,
13.  speed = 10;//***次移动的速度,单位px/ms,隐式地乘以1ms
14.  (function(){
15.    setTimeout(function(){
16.      el.style.left = getCoords(el).left + speed + "px";//移动
17.      speed *= 1.5;//下一次移动的距离
18.      if(getCoords(el).left >= end){
19.        el.style.left = end + "px";
20.      }else{       
21.        setTimeout(arguments.callee,25);//每移动一次停留25毫秒
22.      }
23.    },25)
24.  })()
25.}

明白了加速,减速就好办了。我们给***次移动的距离一个很大的数,往后每次减少一点点,换言之乘以一个小于1的数。但这里有个注意点,如果有一次,它移动的距离少于1px怎么办?!它再往后也是少于1px。浏览器就会忽略这个值,当作0来处理。这样一来,它就会停在中途不动了。为了防止这样可怕的事发生,我们利用Math.ceil来确保其最小移动距离为1px,哪怕***的匀速移动也要抵达终点。

01.//主函数:减速移动
02. var decelerate = function(el){
03.   el.style.position = "absolute";
04.   var begin =  getCoords(el).left,
05.   distance = parseFloat(getStyle(_("taxiway"),"width")) - parseFloat(getStyle(el,"width")),
06.   end = begin + distance,
07.   speed = 100;//***次移动的速度,单位px/ms,隐式地乘以1ms
08.   (function(){
09.     setTimeout(function(){
10.       el.style.left = getCoords(el).left + speed + "px";//移动
11.       speed = Math.ceil(speed * 0.9);//下一次移动的距离
12.       if(getCoords(el).left <= end){
13.         el.style.left = end + "px";
14.       }else{       
15.         setTimeout(arguments.callee,25);
16.       }
17.     },25)
18.   })()
19. }

现在函数的功能还很弱,主要是由于在抽象与制定上有所欠缺,如果克服这些缺点并配合Robert Penner大神的缓动公式,我们就可以搞出花样繁多的缓动效果来。

原文标题:由浅入深javascript的缓动效果

链接:http://www.cnblogs.com/rubylouvre/archive/2009/09/16/1566699.html

【编辑推荐】

  1. JSON是什么?为JavaScript准备的数据格式
  2. 十个最常用的JavaScript自定义函数
  3. 有关JavaScript事件加载的一些延伸思考
  4. JavaScript使用心得汇总:从BOM和DOM谈起
  5. ExtJS在Android模拟器上的运行效果
责任编辑:彭凡 来源: 博客园
相关推荐

2012-10-10 10:22:57

JavaScriptJSjQuery

2011-06-20 06:18:27

ibmdwjava

2010-06-03 18:22:38

Hadoop

2011-04-02 16:37:26

PAT

2010-09-14 17:20:57

2021-01-26 13:27:11

分布 Raft 算法

2010-09-03 10:23:49

PPP Multili

2011-04-01 09:04:09

RIP

2011-04-02 16:33:33

2011-05-23 13:24:01

2010-11-22 16:22:39

MySQL连接查询

2009-08-28 16:37:32

C# for循环

2010-03-03 14:05:36

Python实例应用

2020-08-12 10:25:39

JavaScript开发技术

2009-11-23 17:31:49

PHP时间戳

2011-07-06 16:15:46

iPhone 图片

2009-09-15 09:45:23

Linq动态条件

2009-12-23 15:16:52

WPF数据绑定

2009-11-23 20:16:17

PHP接口特性

2011-04-07 13:09:03

明文验证
点赞
收藏

51CTO技术栈公众号