【问题标题】:Providing multiple arguments to an anonymous function in setInterval在 setInterval 中为匿名函数提供多个参数
【发布时间】:2016-02-22 21:29:59
【问题描述】:

我不确定之前是否有人问过这个 Javascript 问题 - 我找不到它,但如果我错过了,我深表歉意。

我正在尝试创建一个带有复选框的页面,该复选框将淡入/淡出相应的图像。褪色需要1秒,每100ms,图像的不透明度增加或减少0.1;当不透明度达到 0 或 1 时,将停止 setInterval 调用。但是,我不确定如何将参数传递给匿名函数调用。我正在尝试传递两个变量——第一个是图像的ID,从复选框值中获取,另一个是复选框是否被选中,以便函数知道是淡入还是淡出。

但是,我在代码中遇到了问题(见下文),我认为这是由于 setInterval 函数调用中变量的范围 - 这就是为什么我要询问是否将多个参数传递给调用.

例如:

<form action="">
<input type="checkbox" onclick='handleClick(this);' name="skymap" value="aurora">Aurora
<input type="checkbox" onclick='handleClick(this);' name="skymap" value="mainindex">Main Index
</form>

并且功能如下(目前为止)

function handleClick(cb) 
{

var myInterval = setInterval(function () 
{
  if (cb.checked) // tick box checked - fade in.
  {
    document.getElementById( cb.value ).style.opacity+=0.1;  // I'll refactor all these style.opacity calls later on :)

    if( document.getElementById( cb.value ).style.opacity>1 ) // full opacity - stop the timer
    {
        document.getElementById( cb.value ).style.opacity = 1;
        clearInterval(myInterval);
    }
}
else // fade out
{
    document.getElementById( cb.val ).style.opacity-=0.1;

    if( document.getElementById( cb.val ).style.opacity<0 )
    {
        document.getElementById( cb.val ).style.opacity = 0;
        clearInterval(myInterval);
    }
}


}, 100);


}

图像被称为:

<img id="aurora" src="aurora.png" />

【问题讨论】:

  • 我现在没有看到任何参数传入?
  • 这就是问题所在 - 我不知道如何...

标签: javascript setinterval clearinterval


【解决方案1】:

你遇到了一个棘手的问题。

首先,你在 else 部分写了“cb.val”而不是“cb.value”

其次,对象“cb”的不透明度属性是字符串类型。 -= 操作将不透明度值转换为数字,因为您不能对字符串执行减号操作。 += 操作将数字 (0.1) 转换为字符串并添加到不透明度字符串的末尾(例如,如果不透明度为 0.1,则结果将为“0.10.1”)。由于这个值是无效的,它会被设置为最后一个有效的值,你就陷入了循环

这是一个工作示例:

function handleClick(cb) 
{

var myInterval = setInterval(function () 
{
  if (cb.checked) // tick box checked - fade in.
  {
    document.getElementById( cb.value ).style.opacity = parseFloat(document.getElementById( cb.value ).style.opacity) + 0.1  // I'll refactor all these style.opacity calls later on :)

    if( document.getElementById( cb.value ).style.opacity>1 ) // full opacity - stop the timer
    {
        document.getElementById( cb.value ).style.opacity = 1;
        clearInterval(myInterval);
    }
}
else // fade out
{
    document.getElementById( cb.value ).style.opacity-=0.1;

    if( document.getElementById( cb.value ).style.opacity<0 )
    {
        document.getElementById( cb.value ).style.opacity = 0;
        clearInterval(myInterval);
    }
}


}, 100);


}

您可能遇到的另一个问题是,默认情况下未设置 opacity 属性(或者至少您无法确定)。所以第一次, opacity = "",空字符串。这将导致动画中的跳跃。如果检测到空字符串,请务必初始化不透明度。

【讨论】:

  • 谢谢,这正是我需要的! cb.val 和缺乏初始不透明度只是由于我草率的复制和粘贴,但它工作得很好,非常感谢!
【解决方案2】:

您可以只在现有代码中使用 cb.checked,但要回答您的问题:使用 setInterval 和 setTimeout,您只需使用闭包功能来传递变量,因为来自外部范围(函数)的值评估时间可供您使用。在一个非常简单的级别上,您可以执行以下操作:

function myTimeoutClosure(greeting, subject) {
    return function() {
        console.log(greeting + " " + subject);
    };
}
// ...
setTimeout(myTimeoutClosure("Hello", "World"), 500);

【讨论】:

    【解决方案3】:

    可以使用setInterval(function(arg1, arg2, ..){...}, intervalTime, arg1, arg2,...)函数的可选参数

    function handleClick(cb) 
    {
    
        var myInterval = setInterval(function (checked, imgId) 
            {
              if (checked) // tick box checked - fade in.
              {
                document.getElementById( imgId ).style.opacity+=0.1;  // I'll refactor all these style.opacity calls later on :)
    
                if( document.getElementById( imgId ).style.opacity>1 ) // full opacity - stop the timer
                {
                    document.getElementById( imgId ).style.opacity = 1;
                    clearInterval(myInterval);
                }
            }
            else // fade out
            {
                document.getElementById( imgId ).style.opacity-=0.1;
    
                if( document.getElementById( imgId ).style.opacity<0 )
                {
                    document.getElementById( imgId ).style.opacity = 0;
                    clearInterval(myInterval);
                }
            }
            }, 100, cb.checked, cb.value);
    
    }
    

    【讨论】:

      【解决方案4】:

      这是一个可行的示例,您的前进方式可能会出现一些问题,即人们反复点击复选框,并将一堆间隔堆叠在一起。在这种情况下,您有一个函数会在超时后调用自身并逐步完成转换,而不是完全依赖间隔。

      function fadeElement(elem, increment) {
      
        elem.style.opacity = parseFloat(elem.style.opacity) + increment;
      
        if (elem.style.opacity >= 1) {
          elem.style.opacity = 1
        } else if (elem.style.opacity <= 0) {
          elem.style.opacity = 0
        } else {
          clearTimeout(elem.getAttribute('data-timeout'))
          elem.setAttribute('data-timeout', setTimeout(function() {
            fadeElement(elem, increment)
          }, 100))
        }
      }
      
      function handleClick(cb) {
      
        var chkbox = document.getElementById(cb.value);
        var direction = cb.checked ? 0.1 : -0.1;
      
        fadeElement(chkbox, direction)
      
      
      }
      <form action="">
        <input type="checkbox" checked onclick='handleClick(this);' name="skymap" value="aurora">Aurora
        <input type="checkbox" checked onclick='handleClick(this);' name="skymap" value="mainindex">Main Index
      </form>
      <p id="aurora" style="opacity:1">Aurora</p>
      <p id="mainindex" style="opacity:1">Main Index</p>

      【讨论】:

        【解决方案5】:

        这里是一个例子。我希望这是你正在寻找的。请告诉我。

        <form action="">
        <input type="checkbox" class='imageSelect' name="skymap" value="aurora">Aurora
        <input type="checkbox"  class= 'imageSelect' name="skymap" value="mainindex">Main Index
        </form>
        <div id="aurora" style="background:yellow; width:150px; height:40px; float:left; display:none;">Aurora Image </div>
        <div id="mainindex" style="background:blue; width:150px; height:40px;float:left; display:none;">MainIndex Image </div>  
        

        JS:

        function CheckBoxClick(){
            $(".imageSelect").click(function(){
                /*if(this.checked){
                     $("#"+$(this).val()+" ").fadeIn();
                  }else{
                     $("#"+$(this).val()+" ").fadeOut();
                  }*/
             $("#"+$(this).val()+" ").toggle(this.checked)
            });
        };    
        

        淡入淡出效果看起来更好,但不管你是否使用它都是你的决定,两者都有效。这里的代码可以玩:https://jsfiddle.net/dzgppqap/

        PD:记得在页面准备好时添加事件:

        $(document).ready(CheckBoxClick());
        

        【讨论】: