65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 动画入门。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.30/5 (6投票s)

2008年7月24日

CPOL

7分钟阅读

viewsIcon

66059

downloadIcon

378

JavaScript 动画入门。

目录

引言

在过去的几年里,互联网发展迅速。AJAX 等方法的引入推动了网络发展,加上软件、技术和用户对网络期望的不断进步,网页设计标准被推得越来越高。

网页变得越来越用户友好和丰富,实现了流畅的过渡和柔和的图形;这些功能丰富的页面中有一个元素就是动画。许多网站通过淡入淡出或闪烁按钮,或卷起和卷下元素等过渡来实现动画。所有这些动画都可以使用 JavaScript 相当容易地创建,本文将对此进行介绍。

先决条件

为了能够理解本文并使用它,需要对 JavaScript 有一个大致的了解,但由于它只是对 JavaScript 动画的介绍,因此不会深入探讨更复杂的概念和方法。

动画对象

概念

在 JavaScript 中动画对象的概念与动画任何事物都是相同的。被动画化的对象在一定时间段内,以一定的间隔,经过一系列“步骤”进行改变。在每个步骤中,对象可以以多种方式进行改变,这种平稳的运行使得对象看起来是动画的。这种动画概念可以使用 JavaScript 相对容易地实现,如下所述。

一个基本动画

就我个人而言,我最喜欢用 JavaScript 编写的动画是淡入淡出函数,仅仅因为 L 它只改变一个属性(对象的 opacity),所以实现起来非常容易。然而,在深入代码之前,需要解释两个关键函数和样式

  • setTimeout(code, milliseconds):此函数是 JavaScript 库的一部分,在经过指定毫秒数后调用指定的 code。所有浏览器都标准支持它。
  • obj.style.opacity, obj.style.filter:opacity 样式随 CSS2 引入。它在 Internet Explorer 和基于 Mozilla 的浏览器(Firefox、Safari 等)中都受支持,但实现方式不同。在 Internet Explorer 中,它以滤镜的形式实现,值为 alpha(opacity=o),其中 o 是 0-100 之间的数字,0 表示完全透明,100 表示完全不透明;在基于 Mozilla 的浏览器中,它以样式 opacity 的形式实现,值为 0 到 1 之间,其中 0 表示完全透明,1 表示完全不透明。

通过淡入淡出动画,淡入淡出对象的 opacity 从起始 opacity 逐渐增加或减少到结束 opacity。此示例将演示一个淡出动画,从 100% opacity 到 0% opacity,分 10 个“步骤”

<script language="Javascript">
..

//Detect browser for later use
browser = undefined;

if(navigator.userAgent.indexOf("MSIE")!=-1)
  browser = "IE";
else
  browser = "Mozilla";

//Called to fade element
function fade(element)
{
  //We will fade the object in 10 steps
  var steps = 10;
  
  //Set the starting opacity
  setOpacity(element, 1);
  
  //Loops the timer function
  for(i=0; i<steps; ++i) {
    setTimeout(function(){fadeCallback(element);}, (30*i));
  }
}

//Callback to timer function
function fadeCallback(element)
{
  //Get the current opacity
  var opacity=getOpacity(element);
  
  //Set the new opacity
  setOpacity(element, opacity-0.1);
}

//Gets an element's opacity
function getOpacity(element)
{
  var opacity = null;
  
  //Get the opacity based on the current browser used
  if(browser=="IE") {
    filter = element.style.filter;
    if(filter) {
      alpha = filter.split("alpha(opacity=");
      opacity = alpha[1].substr(0,(alpha[1].length-1))/100;
    }
  }
  else {
    opacity = element.style.opacity;
  }
    
  return opacity;
}

//Sets an element's opacity
function setOpacity(element, o)
{
  //Set the opacity based on the current browser used
  if(browser=="IE") {
    element.style.filter = "alpha(opacity=" + (o*100) + ")";
  }
  else {
    element.style.opacity = o;
  }
}

..
</script>

然后可以通过调用 fade(element) 运行动画,其中 element 是对元素的引用,例如

<div style="width: 50px; height: 50px; background-color: red;" onClick="fade(this);">
</div>

它将在点击时淡出 DIV

由于这可能难以理解,我将把每个部分分解成更容易管理的小块

..

if(navigator.userAgent.indexOf("MSIE")!=-1)
  browser = "IE";
else
  browser = "Mozilla";

..

第一段代码只是一个简单的检测浏览器是 Internet Explorer 还是“Mozilla”(非 IE 浏览器)的方法,因为这将在后面获取或设置元素的 opacity 时使用。代码使用 navigator.userAgent 变量,该变量返回当前浏览器标识符 string,然后检查它是否包含“MSIE”,因为这意味着当前浏览器是 Internet Explorer。如果不是,则使用哪个浏览器无关紧要,因为它们都将使用另一个标准 opacity 样式。

fade() 函数

..

function fade(element)
{
  //We will fade the object in 10 steps
  var steps = 10;
  
  //Set the starting opacity
  setOpacity(element, 1);
  
  //Loops the timer function
  for(i=0; i<steps; ++i) {
    setTimeout(function(){fadeCallback(element);}, (30*i));
  }
}

..

此函数用于淡出元素。它接受一个参数 element,它是要淡出的元素的句柄。setTimeout() 函数也在此处使用。它在循环中调用以调用 fadeCallback() 函数,该函数将更改淡出元素的 opacity。(30*i) 作为毫秒数,以便每 30 毫秒调用一次 fadeCallback()elementopacity 设置为 1 作为起始 opacity。另请注意,回调函数周围有 function() { .. }。这是因为当函数应用了参数时,如果简单地写成 fadeCallback(element),那么函数将立即被调用,而不是设置为计时器函数。

fadeCallback() 函数

..

function fadeCallback(element)
{
  //Get the current opacity
  var opacity=getOpacity(element);
  
  //Set the new opacity
  setOpacity(element, opacity-0.1);
}

..

此函数是由 setTimeout() 函数调用的回调函数。它检索正在淡出元素的当前 opacity,然后通过将当前 opacity 减少 0.1 来设置新的 opacity。

getOpacity() 函数

..

function getOpacity(element)
{
  var opacity = null;
  
  //Get the opacity based on the current browser used
  if(browser=="IE") {
    filter = element.style.filter;
    if(filter) {
      alpha = filter.split("alpha(opacity=");
      opacity = alpha[1].substr(0,(alpha[1].length-1))/100;
    }
  }
  else {
    opacity = element.style.opacity;
  }
    
  return opacity;
}

..

此函数获取正在淡出元素的当前 opacity。如前所述,Internet Explorer 和基于 Mozilla 的浏览器处理 opacity 的方式不同,因此此函数使用先前设置的 browser 变量来确定要使用的方法。然后返回 opacity 以供使用,比例介于 01 之间(其中 0 表示完全透明,1 表示完全不透明)。

setOpacity() 函数

..

function setOpacity(element, o)
{
  //Set the opacity based on the current browser used
  if(browser=="IE") {
    element.style.filter = "alpha(opacity=" + (o*100) + ")";
  }
  else {
    element.style.opacity = o;
  }
}

..

此函数设置正在淡出元素的 opacity。与 getOpacity() 函数一样,它使用先前设置的 browser 变量来区分 Internet Explorer 和基于 Mozilla 的浏览器 opacity 处理。

如前所述,由于这只是一篇入门文章,我只介绍了如何淡出元素,但是,淡入元素的原理是相同的,只是起始 opacity 为 0,并且在每个步骤中 opacity 都会增加。

setTimeout() 还是 setInterval()?

有什么区别?

JavaScript 中有两个关键函数可用于动画对象。第一个是已经演示过的 setTimeout(),另一个是 setInterval()。它们都执行类似的功能,但有一个细微的区别。它们的共同点是它们都在经过指定毫秒数后调用一个函数,但是 setTimeout() 只在时间段结束后调用此函数一次,而 setInterval() 在每经过 x 毫秒后循环调用该函数,直到调用 clearInterval() 函数为止。

那么哪个函数是最好的呢?在尝试了这两种方法之后,我发现它们都同样有用,并且都需要编写代码来检查动画是否完成;对于 setTimeout()fade() 函数根据步骤数计算它必须被调用的次数,而对于 setInterval(),回调函数中的代码决定动画是否完成。为了这个简单的动画演示,setTimeout() 更合适,因为动画回调函数被调用的次数是在 fade() 函数中计算的,而使用 setInterval(),动画是否完成是在动画回调函数中确定的,并且必须存储计时器 ID(请参阅下面的示例)。但是,我发现对于更大规模、更复杂的动画,setInterval() 函数更合适,特别是对于每步改变不透明度增量/减量等方法。

使用 setInterval() 的示例

使用 setInterval() 函数的动画示例如下

..

//Detect browser for later use
..

//Stores the setInterval() ID
timer = null;

//Called to fade element
function fade(element)
{
  //Set the timer interval to 30ms and store the setInterval() ID
  timer = setInterval(function(){fadeCallback(element);}, 30);
}

//Callback to timer function
function fadeCallback(element)
{
  //Get the current opacity
  var opacity=getOpacity(element);
  
  //Clears the interval if at the end of the animation
  if((opacity-0.1)==0)
    clearInterval(timer);
  
  //Set the new opacity
  setOpacity(element, opacity-0.1);
}

//Gets an element's opacity
function getOpacity(element)
{
  ..
}

//Sets an element's opacity
function setOpacity(element, o)
{
  ..
}

..

这个例子与使用 setTimeout() 函数的例子非常相似,但有一些明显的区别。如您所见,用于确定动画是否完成的代码包含在动画回调函数中

if((opacity-0.1)==0)
  clearInterval(timer);

这利用了 clearInterval() 函数,它删除使用 setInterval() 函数创建的计时器,其唯一参数是所创建计时器的 ID。如示例所示,在调用 setInterval() 函数时返回计时器 ID

timer = setInterval(function(){fadeCallback(element);}, 30);

如您所见,setInterval() ID **必须**存储,以便在使用后可以清除计时器。

结论

阅读本文后,您应该能够

  • 了解 JavaScript 计时器的工作原理
  • 能够实现一个基本的对象动画器
  • 理解 setTimeout()setInterval() 函数之间的区别

历史

  • 2008 年 7 月 23 日:未经修改的第一版
© . All rights reserved.