11

这是一个快速(坏掉的)jsfiddle:http: //jsfiddle.net/wH2qF/

由于某种原因,这不起作用......是因为我在另一个 setTimeout 的处理程序中有一个 setTimeout 吗?

$(function() {
   $("#Volume").click(function() {
      setTimeout(triggerVolumeChange, 4000);
      function triggerVolumeChange() 
      {
          var volumeDiv = document.getElementById("volumeNumber");
          var volumeOld = 8;
          var volumeNew = 37;
          var timeNew = (1000/(volumeNew-volumeOld));
          changeVolume();
                        
          function changeVolume()
          {
             volumeDiv.innerHTML = volumeOld;
             volumeOld++;
             if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
          };
      });
});

应该指定,为了清楚起见,我从该 Click 函数中删除了其他内容,并澄清了哪些内容不能完全正常工作,好吧,基本上,我点击并没有任何反应,而如果我删掉这段代码,它就可以正常工作.. .实际上vars的设置也可以正常工作(我自然认为)但是当我粘贴或取消注释changeVolume()函数时,点击再次停止工作......有什么想法吗?

--

另一个澄清:我想要做的是,在点击时,在一个字符串中模拟从 8 到 37 的音量......因此该函数内部的 setTimeout 。

--

根据你的要求,这是整个代码......我怀疑它是否有意义,但它是......仅供参考,点击这将触发一些动画来模拟我正在设计的应用程序的流程。 .

<script>
            $(function() {
                $("#Volume").click(function() {
                                        
                    var userPrompt = document.getElementById("userPrompt")
                    userPrompt.innerHTML = "Change volume to 37";
                                        
                    var avatarIcon = document.getElementById("avatarIcon");
                    avatarIcon.innerHTML = "<img src='imgs/haloIcons-volume_82x76.png' alt='Volume'/>";
                
                    var hints = document.getElementById("hints");
                    hints.style.opacity = 0;
                    $(".dragonTvOut").toggleClass("dragonTvIn");
                    
                    setTimeout(triggerP, 1000);
                    function triggerP()
                    {
                        var halo = document.getElementById('avatar');
                        if( 'process' in halo ) { 
                            halo.process();
                        };
                    };
                    
                    setTimeout(triggerUserPrompt, 2000);
                    function triggerUserPrompt() 
                    {
                        document.getElementById("userPrompt").className = "userPromptIn";
                    };
                    
                    setTimeout(triggerVolumeChange, 4000);
                    function triggerVolumeChange() 
                    {
                        document.getElementById("userPrompt").className = "userPromptEnd";
                        
                        var halo = document.getElementById('avatar');
                        if( 'resume' in halo ) { 
                            halo.resume();
                        }

                        document.getElementById("avatarIcon").className = "avatarIconEnd";
                        
                        var volumeDiv = document.getElementById("volumeNumber");
                        var volumeOld = 8;
                        var volumeNew = 37;
                        var timeNew = (1000/(volumeNew-volumeOld));
                        changeVolume();
                        
                        function changeVolume()
                        {
                            volumeDiv.innerHTML = volumeOld;
                            volumeOld++;
                            if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
                        }​;
                        
                        var side = 100;
                        var paper = new Raphael(volumeArcAnim, 100, 300);
                        
                        paper.customAttributes.arc = function (xloc, yloc, value, total, R) {

                            var alpha = 360 / total * value,
                                a = (90 - alpha) * Math.PI / 180,
                                x = xloc + R * Math.cos(a),
                                y = yloc - R * Math.sin(a),
                                path;
                            if (total == value) {
                                path = [
                                    ["M", xloc, yloc - R],
                                    ["A", R, R, 0, 1, 1, xloc - 0.01, yloc - R]
                                ];
                            } else {
                                path = [
                                    ["M", xloc, yloc - R],
                                    ["A", R, R, 0, +(alpha > 180), 1, x, y]
                                ];
                            }
                            return {
                                path: path
                            };
                        };
                    
                        var arcWidth = 87;
                        var strokeRadius = arcWidth/2;
                        
                        var indicatorArc = paper.path().attr({
                            "stroke": "#ffffff",
                            "stroke-width": 3,
                            arc: [side/2, side/2, 12, 100, strokeRadius]
                        });
                        
                        indicatorArc.animate({
                            arc: [side/2, side/2, 60, 100, strokeRadius]
                        }, 1500, "<>", function(){
                            // anim complete here
                        });
                        
                    };
                                            
                });
            });
            </script>
4

5 回答 5

5

是的,你可以setTimeout()在另一个里面——这是用于重复定时事件的典型机制。

你的不工作的原因与它setTimeout()本身无关。这与您嵌套函数的方式有关。

里面的changeVolume()函数triggerVolumeChange()意味着你不能直接使用它的名字来引用它。

对您来说最快的解决方案是删除嵌套,以便changeVolume()在根级别而不是嵌套在内部triggerVolumeChange()

于 2012-12-14T22:37:48.003 回答
4

你错过了一个}

$(function() {
   $("#Volume").click(function() {
      setTimeout(triggerVolumeChange, 4000);
      function triggerVolumeChange()
      {
          var volumeDiv = document.getElementById("volumeNumber");
          var volumeOld = 8;
          var volumeNew = 37;
          var timeNew = (1000/(volumeNew-volumeOld));
          changeVolume();

          function changeVolume()
          {
             volumeDiv.innerHTML = volumeOld;
             volumeOld++;
                 if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
          };
      } // that one was missing
   });
});
于 2012-12-14T22:35:57.753 回答
3

在您损坏的示例http://jsfiddle.net/wH2qF/中存在一些问题

  • 你忘了告诉 jsfiddle 使用 jQuery
  • 卷跨度的 id(在 JS 中)是ph但应该是volumeNumber(如在 HTML 中)

单击此处查看工作版本

如果你从 jsfiddle 的库中选择了 jQuery,你会看到一个错误

未捕获的类型错误:无法将属性“innerHTML”设置为 null

这使我相信您的 jsfiddle 不能很好地代表您的问题。也许尝试创建另一个减少,因为您添加的那个只有“愚蠢”的错误?

于 2012-12-14T23:15:57.737 回答
0

If you don't want to use setInterval(), you can make the code work with these changes:

$(function() {
    $("#Volume").click(function() {
        setTimeout(triggerVolumeChange, 4000);
        function triggerVolumeChange () {
            var volumeDiv = document.getElementById("volumeNumber");
            var volumeOld = 8;
            var volumeNew = 37;
            var timeNew = (1000/(volumeNew-volumeOld));
            var changeVolume = function () {
                volumeDiv.innerHTML = volumeOld;
                volumeOld++;
                if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
            };
            changeVolume();
        }
    });
});

Working demo at jsFiddle.

于 2012-12-14T23:06:24.477 回答
0

从技术上讲,计时器的启动位置没有区别。在大多数情况下,它被实现为带有标识符和相关回调处理程序的计时器列表。

所以如果你的逻辑是正确的就可以了。没有不可预知的条件带来无限的调用序列,也没有无限量的超时实例等等。

例如模仿setInterval功能:

// Bad (unexpected multiple sequences started per each event)

const handler = () => {
  setTimeout(handler)
}

<Button onClick={handler} />
// Good (previous interval closed before start new one)

const [id, idUpdate] = useState(-1)

const handler = () => {
  const id = setTimeout(handler)
  idUpdate(id)
}

const start = () => {
  if(id !===-1) clearTimeout(id)
  idUpdate(-1)
  handler()
}

<Button onClick={start} />

或其他一些

// Bad (infinite events with small time will take all cpu time)

const handler = () => {
  setTimeout(handler, 0) // actually mean several ms
}
// Good (special condition for finish iterations)

let count = 20

const handler = () => {
  if(!count) return
  count--
  setTimeout(handler, 0)
}
于 2020-09-24T15:29:49.160 回答