1

以下代码让我感到困惑。我的目标是在一段时间内将 HTML 元素从一个不透明度级别淡化到另一个级别。下面是我的 dimScreen() 方法,用于创建一个变暗的叠加层并将其淡入。

var overlay;

function dimScreen()
{
   if(!overlay)
   {
      overlay = document.createElement('div');
      overlay.setAttribute('id', 'overlay');
      overlay.style.width = '100%';
      overlay.style.height = '100%';
      overlay.style.zindex = '1000';
      overlay.style.background = '#000013';
      overlay.style.position = 'fixed';
      overlay.style.left = '0';
      overlay.style.top = '0';
      overlay.style.opacity = '.0';

      document.body.appendChild(overlay);
      fade('overlay', 0, 75, 200);
   }
}

这是我的工作淡入淡出功能:

function fade(eID, startOpacity, stopOpacity, duration)
{
   var speed = Math.round(duration / 100);
   var timer = 0;
   if (startOpacity < stopOpacity)
   {     // fade in
      for (var i=startOpacity; i<=stopOpacity; i++)
      {
         setTimeout("setOpacity('"+eID+"',"+i+")", timer * speed);
         timer++;
      } return;
   }
   for (var i=startOpacity; i>=stopOpacity; i--)
   {     // fade out
      setTimeout("setOpacity('"+eID+"',"+i+")", timer * speed);
      timer++;
   }
}

还有我的工作 setOpacity:

function setOpacity(eID, opacityLevel)
{
   var eStyle = document.getElementById(eID).style;
   eStyle.opacity = opacityLevel / 100;
   eStyle.filter = 'alpha(opacity='+opacityLevel+')';
}

但是,我想将我的 fade() 函数更改为使用以下形式的闭包:

setTimeout(function(){setOpacity(eID,i)}, timer * speed);

然后我可以传入实际的覆盖 div,而不是 id 'overlay'。然而,当我这样做时,而不是动画覆盖 div 的逐渐淡入,它只是直接到最后一个不透明度值,没有过渡。为什么会这样?

我有一种感觉,这是我想念的简单的东西,因为我已经看了很长时间了。任何帮助,将不胜感激!

4

1 回答 1

0

It's too late and still too hot to think much here right now. (2.30am, 28°C) Forgive me if my explanation falls short of expectations.

Basically, because you construct text strings to pass to setTimeout, each call gets the correct value for i. Since to pass an actual element, you can't use the string trick, you end up using the same value of i for each call to setOpacity.

As your question title indicates you understand, you need to use closures to get it to work right. I can't find(only followed 2 or 3 links) a good tute/S.O question that explains it in a way that seems relevant and clear.

Hope the code will be of use.

var overlay;
function dimScreen()
{
   if(!overlay)
   {
      overlay = document.createElement('div');
      overlay.setAttribute('id', 'overlay');
      overlay.style.width = '100%';
      overlay.style.height = '100%';
      overlay.style.zindex = '1000';
      overlay.style.background = '#000013';
      overlay.style.position = 'fixed';
      overlay.style.left = '0';
      overlay.style.top = '0';
      overlay.style.opacity = '.0';

      document.body.appendChild(overlay);
      myFade(overlay, 0, 75, 2000);
   }
}
function myFade(element, startOpacity, stopOpacity, duration)
{
   var speed = Math.round(duration / 100);
   var timer = 0;
   if (startOpacity < stopOpacity)
   {     // fade in
      for (var i=startOpacity; i<=stopOpacity; i++)
      {
        (
            function()
            {
                var myI = i;
                setTimeout(function(){mySetOpacity(element,myI)}, timer * speed);
            }
        )()
         timer++;
      }
   }

   else
   for (var i=startOpacity; i>=stopOpacity; i--)
   {     // fade out
      for (var i=startOpacity; i<=stopOpacity; i++)
      {
        (
            function()
            {
                var myI = i;
                setTimeout(function(){mySetOpacity(element,myI)}, timer * speed);
            }
        )()
         timer++;
      }
   }
}

function mySetOpacity(el, opacityLevel)
{
   var eStyle = el.style;
   eStyle.opacity = opacityLevel / 100;
   eStyle.filter = 'alpha(opacity='+opacityLevel+')';
}
于 2013-03-12T15:42:36.130 回答